Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
70a27a33
V
vscode
项目概览
xxadev
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
70a27a33
编写于
12月 13, 2017
作者:
J
Johannes Rieken
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add CLIPBOARD snippet variable, #40153
上级
50b7c7bd
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
129 addition
and
46 deletion
+129
-46
src/vs/editor/contrib/snippet/snippetSession.ts
src/vs/editor/contrib/snippet/snippetSession.ts
+11
-2
src/vs/editor/contrib/snippet/snippetVariables.ts
src/vs/editor/contrib/snippet/snippetVariables.ts
+67
-18
src/vs/editor/contrib/snippet/test/snippetVariables.test.ts
src/vs/editor/contrib/snippet/test/snippetVariables.test.ts
+49
-24
src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.ts
.../parts/snippets/electron-browser/snippets.contribution.ts
+2
-2
未找到文件。
src/vs/editor/contrib/snippet/snippetSession.ts
浏览文件 @
70a27a33
...
...
@@ -15,9 +15,11 @@ import { Range } from 'vs/editor/common/core/range';
import
{
IPosition
}
from
'
vs/editor/common/core/position
'
;
import
{
groupBy
}
from
'
vs/base/common/arrays
'
;
import
{
dispose
}
from
'
vs/base/common/lifecycle
'
;
import
{
EditorSnippet
VariableResolver
}
from
'
./snippetVariables
'
;
import
{
SelectionBasedVariableResolver
,
CompositeSnippetVariableResolver
,
ModelBasedVariableResolver
,
ClipboardBased
VariableResolver
}
from
'
./snippetVariables
'
;
import
{
ModelDecorationOptions
}
from
'
vs/editor/common/model/textModelWithDecorations
'
;
import
{
ICodeEditor
}
from
'
vs/editor/browser/editorBrowser
'
;
import
{
IClipboardService
}
from
'
vs/platform/clipboard/common/clipboardService
'
;
import
{
optional
}
from
'
vs/platform/instantiation/common/instantiation
'
;
export
class
OneSnippet
{
...
...
@@ -269,6 +271,9 @@ export class SnippetSession {
const
edits
:
IIdentifiedSingleEditOperation
[]
=
[];
const
snippets
:
OneSnippet
[]
=
[];
const
modelBasedVariableResolver
=
new
ModelBasedVariableResolver
(
model
);
const
clipboardVariableResolver
=
new
ClipboardBasedVariableResolver
(
editor
.
invokeWithinContext
(
accessor
=>
accessor
.
get
(
IClipboardService
,
optional
)));
let
delta
=
0
;
// know what text the overwrite[Before|After] extensions
...
...
@@ -310,7 +315,11 @@ export class SnippetSession {
const
snippet
=
new
SnippetParser
()
.
parse
(
adjustedTemplate
,
true
,
enforceFinalTabstop
)
.
resolveVariables
(
new
EditorSnippetVariableResolver
(
model
,
selection
));
.
resolveVariables
(
new
CompositeSnippetVariableResolver
([
modelBasedVariableResolver
,
clipboardVariableResolver
,
new
SelectionBasedVariableResolver
(
model
,
selection
)
]));
const
offset
=
model
.
getOffsetAt
(
start
)
+
delta
;
delta
+=
snippet
.
toString
().
length
-
model
.
getValueLengthInRange
(
snippetSelection
);
...
...
src/vs/editor/contrib/snippet/snippetVariables.ts
浏览文件 @
70a27a33
...
...
@@ -10,21 +10,40 @@ import { IModel } from 'vs/editor/common/editorCommon';
import
{
Selection
}
from
'
vs/editor/common/core/selection
'
;
import
{
VariableResolver
,
Variable
,
Text
}
from
'
vs/editor/contrib/snippet/snippetParser
'
;
import
{
getLeadingWhitespace
,
commonPrefixLength
}
from
'
vs/base/common/strings
'
;
import
{
IClipboardService
}
from
'
vs/platform/clipboard/common/clipboardService
'
;
export
const
KnownSnippetVariableNames
=
Object
.
freeze
({
'
SELECTION
'
:
true
,
'
CLIPBOARD
'
:
true
,
'
TM_SELECTED_TEXT
'
:
true
,
'
TM_CURRENT_LINE
'
:
true
,
'
TM_CURRENT_WORD
'
:
true
,
'
TM_LINE_INDEX
'
:
true
,
'
TM_LINE_NUMBER
'
:
true
,
'
TM_FILENAME
'
:
true
,
'
TM_FILENAME_BASE
'
:
true
,
'
TM_DIRECTORY
'
:
true
,
'
TM_FILEPATH
'
:
true
,
});
export
class
CompositeSnippetVariableResolver
implements
VariableResolver
{
constructor
(
private
readonly
_delegates
:
VariableResolver
[])
{
//
}
export
class
EditorSnippetVariableResolver
implements
VariableResolver
{
static
readonly
VariableNames
=
Object
.
freeze
({
'
SELECTION
'
:
true
,
'
TM_SELECTED_TEXT
'
:
true
,
'
TM_CURRENT_LINE
'
:
true
,
'
TM_CURRENT_WORD
'
:
true
,
'
TM_LINE_INDEX
'
:
true
,
'
TM_LINE_NUMBER
'
:
true
,
'
TM_FILENAME
'
:
true
,
'
TM_FILENAME_BASE
'
:
true
,
'
TM_DIRECTORY
'
:
true
,
'
TM_FILEPATH
'
:
true
,
});
resolve
(
variable
:
Variable
):
string
{
for
(
const
delegate
of
this
.
_delegates
)
{
let
value
=
delegate
.
resolve
(
variable
);
if
(
value
!==
void
0
)
{
return
value
;
}
}
return
undefined
;
}
}
export
class
SelectionBasedVariableResolver
implements
VariableResolver
{
constructor
(
private
readonly
_model
:
IModel
,
...
...
@@ -82,8 +101,24 @@ export class EditorSnippetVariableResolver implements VariableResolver {
}
else
if
(
name
===
'
TM_LINE_NUMBER
'
)
{
return
String
(
this
.
_selection
.
positionLineNumber
);
}
return
undefined
;
}
}
export
class
ModelBasedVariableResolver
implements
VariableResolver
{
constructor
(
private
readonly
_model
:
IModel
)
{
//
}
}
else
if
(
name
===
'
TM_FILENAME
'
)
{
resolve
(
variable
:
Variable
):
string
{
const
{
name
}
=
variable
;
if
(
name
===
'
TM_FILENAME
'
)
{
return
basename
(
this
.
_model
.
uri
.
fsPath
);
}
else
if
(
name
===
'
TM_FILENAME_BASE
'
)
{
...
...
@@ -101,9 +136,23 @@ export class EditorSnippetVariableResolver implements VariableResolver {
}
else
if
(
name
===
'
TM_FILEPATH
'
)
{
return
this
.
_model
.
uri
.
fsPath
;
}
else
{
return
undefined
;
}
return
undefined
;
}
}
export
class
ClipboardBasedVariableResolver
implements
VariableResolver
{
constructor
(
private
readonly
_clipboardService
:
IClipboardService
)
{
//
}
resolve
(
variable
:
Variable
):
string
{
return
(
variable
.
name
===
'
CLIPBOARD
'
&&
this
.
_clipboardService
)
?
this
.
_clipboardService
.
readText
()
||
undefined
:
undefined
;
}
}
src/vs/editor/contrib/snippet/test/snippetVariables.test.ts
浏览文件 @
70a27a33
...
...
@@ -8,14 +8,15 @@ import * as assert from 'assert';
import
{
isWindows
}
from
'
vs/base/common/platform
'
;
import
URI
from
'
vs/base/common/uri
'
;
import
{
Selection
}
from
'
vs/editor/common/core/selection
'
;
import
{
EditorSnippet
VariableResolver
}
from
'
vs/editor/contrib/snippet/snippetVariables
'
;
import
{
SnippetParser
,
Variable
}
from
'
vs/editor/contrib/snippet/snippetParser
'
;
import
{
SelectionBasedVariableResolver
,
CompositeSnippetVariableResolver
,
ModelBasedVariableResolver
,
ClipboardBased
VariableResolver
}
from
'
vs/editor/contrib/snippet/snippetVariables
'
;
import
{
SnippetParser
,
Variable
,
VariableResolver
}
from
'
vs/editor/contrib/snippet/snippetParser
'
;
import
{
Model
}
from
'
vs/editor/common/model/model
'
;
import
{
IClipboardService
}
from
'
vs/platform/clipboard/common/clipboardService
'
;
suite
(
'
Snippet Variables Resolver
'
,
function
()
{
let
model
:
Model
;
let
resolver
:
EditorSnippet
VariableResolver
;
let
resolver
:
VariableResolver
;
setup
(
function
()
{
model
=
Model
.
createFromString
([
...
...
@@ -24,14 +25,17 @@ suite('Snippet Variables Resolver', function () {
'
this is line three
'
].
join
(
'
\n
'
),
undefined
,
undefined
,
URI
.
parse
(
'
file:///foo/files/text.txt
'
));
resolver
=
new
EditorSnippetVariableResolver
(
model
,
new
Selection
(
1
,
1
,
1
,
1
));
resolver
=
new
CompositeSnippetVariableResolver
([
new
ModelBasedVariableResolver
(
model
),
new
SelectionBasedVariableResolver
(
model
,
new
Selection
(
1
,
1
,
1
,
1
)),
]);
});
teardown
(
function
()
{
model
.
dispose
();
});
function
assertVariableResolve
(
resolver
:
EditorSnippet
VariableResolver
,
varName
:
string
,
expected
:
string
)
{
function
assertVariableResolve
(
resolver
:
VariableResolver
,
varName
:
string
,
expected
:
string
)
{
const
snippet
=
new
SnippetParser
().
parse
(
`$
${
varName
}
`
);
const
variable
=
<
Variable
>
snippet
.
children
[
0
];
variable
.
resolve
(
resolver
);
...
...
@@ -55,9 +59,8 @@ suite('Snippet Variables Resolver', function () {
assertVariableResolve
(
resolver
,
'
TM_FILEPATH
'
,
'
/foo/files/text.txt
'
);
}
resolver
=
new
EditorSnippetVariableResolver
(
Model
.
createFromString
(
''
,
undefined
,
undefined
,
URI
.
parse
(
'
http://www.pb.o/abc/def/ghi
'
)),
new
Selection
(
1
,
1
,
1
,
1
)
resolver
=
new
ModelBasedVariableResolver
(
Model
.
createFromString
(
''
,
undefined
,
undefined
,
URI
.
parse
(
'
http://www.pb.o/abc/def/ghi
'
))
);
assertVariableResolve
(
resolver
,
'
TM_FILENAME
'
,
'
ghi
'
);
if
(
!
isWindows
)
{
...
...
@@ -65,9 +68,8 @@ suite('Snippet Variables Resolver', function () {
assertVariableResolve
(
resolver
,
'
TM_FILEPATH
'
,
'
/abc/def/ghi
'
);
}
resolver
=
new
EditorSnippetVariableResolver
(
Model
.
createFromString
(
''
,
undefined
,
undefined
,
URI
.
parse
(
'
mem:fff.ts
'
)),
new
Selection
(
1
,
1
,
1
,
1
)
resolver
=
new
ModelBasedVariableResolver
(
Model
.
createFromString
(
''
,
undefined
,
undefined
,
URI
.
parse
(
'
mem:fff.ts
'
))
);
assertVariableResolve
(
resolver
,
'
TM_DIRECTORY
'
,
''
);
assertVariableResolve
(
resolver
,
'
TM_FILEPATH
'
,
'
fff.ts
'
);
...
...
@@ -76,24 +78,24 @@ suite('Snippet Variables Resolver', function () {
test
(
'
editor variables, selection
'
,
function
()
{
resolver
=
new
EditorSnippet
VariableResolver
(
model
,
new
Selection
(
1
,
2
,
2
,
3
));
resolver
=
new
SelectionBased
VariableResolver
(
model
,
new
Selection
(
1
,
2
,
2
,
3
));
assertVariableResolve
(
resolver
,
'
TM_SELECTED_TEXT
'
,
'
his is line one
\n
th
'
);
assertVariableResolve
(
resolver
,
'
TM_CURRENT_LINE
'
,
'
this is line two
'
);
assertVariableResolve
(
resolver
,
'
TM_LINE_INDEX
'
,
'
1
'
);
assertVariableResolve
(
resolver
,
'
TM_LINE_NUMBER
'
,
'
2
'
);
resolver
=
new
EditorSnippet
VariableResolver
(
model
,
new
Selection
(
2
,
3
,
1
,
2
));
resolver
=
new
SelectionBased
VariableResolver
(
model
,
new
Selection
(
2
,
3
,
1
,
2
));
assertVariableResolve
(
resolver
,
'
TM_SELECTED_TEXT
'
,
'
his is line one
\n
th
'
);
assertVariableResolve
(
resolver
,
'
TM_CURRENT_LINE
'
,
'
this is line one
'
);
assertVariableResolve
(
resolver
,
'
TM_LINE_INDEX
'
,
'
0
'
);
assertVariableResolve
(
resolver
,
'
TM_LINE_NUMBER
'
,
'
1
'
);
resolver
=
new
EditorSnippet
VariableResolver
(
model
,
new
Selection
(
1
,
2
,
1
,
2
));
resolver
=
new
SelectionBased
VariableResolver
(
model
,
new
Selection
(
1
,
2
,
1
,
2
));
assertVariableResolve
(
resolver
,
'
TM_SELECTED_TEXT
'
,
undefined
);
assertVariableResolve
(
resolver
,
'
TM_CURRENT_WORD
'
,
'
this
'
);
resolver
=
new
EditorSnippet
VariableResolver
(
model
,
new
Selection
(
3
,
1
,
3
,
1
));
resolver
=
new
SelectionBased
VariableResolver
(
model
,
new
Selection
(
3
,
1
,
3
,
1
));
assertVariableResolve
(
resolver
,
'
TM_CURRENT_WORD
'
,
undefined
);
});
...
...
@@ -117,21 +119,18 @@ suite('Snippet Variables Resolver', function () {
assertVariableResolve
(
resolver
,
'
TM_FILENAME_BASE
'
,
'
text
'
);
resolver
=
new
EditorSnippetVariableResolver
(
Model
.
createFromString
(
''
,
undefined
,
undefined
,
URI
.
parse
(
'
http://www.pb.o/abc/def/ghi
'
)),
new
Selection
(
1
,
1
,
1
,
1
)
resolver
=
new
ModelBasedVariableResolver
(
Model
.
createFromString
(
''
,
undefined
,
undefined
,
URI
.
parse
(
'
http://www.pb.o/abc/def/ghi
'
))
);
assertVariableResolve
(
resolver
,
'
TM_FILENAME_BASE
'
,
'
ghi
'
);
resolver
=
new
EditorSnippetVariableResolver
(
Model
.
createFromString
(
''
,
undefined
,
undefined
,
URI
.
parse
(
'
mem:.git
'
)),
new
Selection
(
1
,
1
,
1
,
1
)
resolver
=
new
ModelBasedVariableResolver
(
Model
.
createFromString
(
''
,
undefined
,
undefined
,
URI
.
parse
(
'
mem:.git
'
))
);
assertVariableResolve
(
resolver
,
'
TM_FILENAME_BASE
'
,
'
.git
'
);
resolver
=
new
EditorSnippetVariableResolver
(
Model
.
createFromString
(
''
,
undefined
,
undefined
,
URI
.
parse
(
'
mem:foo.
'
)),
new
Selection
(
1
,
1
,
1
,
1
)
resolver
=
new
ModelBasedVariableResolver
(
Model
.
createFromString
(
''
,
undefined
,
undefined
,
URI
.
parse
(
'
mem:foo.
'
))
);
assertVariableResolve
(
resolver
,
'
TM_FILENAME_BASE
'
,
'
foo
'
);
});
...
...
@@ -208,4 +207,30 @@ suite('Snippet Variables Resolver', function () {
);
});
test
(
'
Add variable to insert value from clipboard to a snippet #40153
'
,
function
()
{
let
readTextResult
:
string
;
let
_throw
=
()
=>
{
throw
new
Error
();
};
let
resolver
=
new
ClipboardBasedVariableResolver
(
new
class
implements
IClipboardService
{
_serviceBrand
:
any
;
readText
():
string
{
return
readTextResult
;
}
writeText
=
_throw
;
readFindText
=
_throw
;
writeFindText
=
_throw
;
});
readTextResult
=
undefined
;
assertVariableResolve
(
resolver
,
'
CLIPBOARD
'
,
undefined
);
readTextResult
=
null
;
assertVariableResolve
(
resolver
,
'
CLIPBOARD
'
,
undefined
);
readTextResult
=
''
;
assertVariableResolve
(
resolver
,
'
CLIPBOARD
'
,
undefined
);
readTextResult
=
'
foo
'
;
assertVariableResolve
(
resolver
,
'
CLIPBOARD
'
,
'
foo
'
);
assertVariableResolve
(
resolver
,
'
foo
'
,
undefined
);
assertVariableResolve
(
resolver
,
'
cLIPBOARD
'
,
undefined
);
});
});
src/vs/workbench/parts/snippets/electron-browser/snippets.contribution.ts
浏览文件 @
70a27a33
...
...
@@ -20,7 +20,7 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'
import
{
LanguageId
}
from
'
vs/editor/common/modes
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
SnippetParser
,
Variable
,
Placeholder
,
Text
}
from
'
vs/editor/contrib/snippet/snippetParser
'
;
import
{
EditorSnippetVariableResolver
}
from
'
vs/editor/contrib/snippet/snippetVariables
'
;
import
{
KnownSnippetVariableNames
}
from
'
vs/editor/contrib/snippet/snippetVariables
'
;
export
const
ISnippetsService
=
createDecorator
<
ISnippetsService
>
(
'
snippetService
'
);
...
...
@@ -107,7 +107,7 @@ export class Snippet {
if
(
marker
instanceof
Variable
&&
marker
.
children
.
length
===
0
&&
!
EditorSnippetVariableResolver
.
VariableNames
[
marker
.
name
]
&&
!
KnownSnippet
VariableNames
[
marker
.
name
]
)
{
// a 'variable' without a default value and not being one of our supported
// variables is automatically turned into a placeholder. This is to restore
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录