Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
0f6df630
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,发现更多精彩内容 >>
提交
0f6df630
编写于
11月 20, 2019
作者:
J
Johannes Rieken
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
highlight future replace range, add setting to disable, #10266
上级
6be5444b
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
219 addition
and
85 deletion
+219
-85
src/vs/editor/common/config/editorOptions.ts
src/vs/editor/common/config/editorOptions.ts
+11
-0
src/vs/editor/contrib/suggest/suggestController.ts
src/vs/editor/contrib/suggest/suggestController.ts
+105
-85
src/vs/editor/contrib/suggest/suggestRangeHighlighter.ts
src/vs/editor/contrib/suggest/suggestRangeHighlighter.ts
+98
-0
src/vs/editor/contrib/suggest/test/completionModel.test.ts
src/vs/editor/contrib/suggest/test/completionModel.test.ts
+1
-0
src/vs/monaco.d.ts
src/vs/monaco.d.ts
+4
-0
未找到文件。
src/vs/editor/common/config/editorOptions.ts
浏览文件 @
0f6df630
...
@@ -2354,6 +2354,10 @@ export interface ISuggestOptions {
...
@@ -2354,6 +2354,10 @@ export interface ISuggestOptions {
* Overwrite word ends on accept. Default to false.
* Overwrite word ends on accept. Default to false.
*/
*/
overwriteOnAccept
?:
boolean
;
overwriteOnAccept
?:
boolean
;
/**
* Should the editor highlight what text suggest will replace.
*/
highlightReplaceRange
?:
boolean
;
/**
/**
* Enable graceful matching. Defaults to true.
* Enable graceful matching. Defaults to true.
*/
*/
...
@@ -2487,6 +2491,7 @@ class EditorSuggest extends BaseEditorOption<EditorOption.suggest, InternalSugge
...
@@ -2487,6 +2491,7 @@ class EditorSuggest extends BaseEditorOption<EditorOption.suggest, InternalSugge
constructor
()
{
constructor
()
{
const
defaults
:
InternalSuggestOptions
=
{
const
defaults
:
InternalSuggestOptions
=
{
overwriteOnAccept
:
false
,
overwriteOnAccept
:
false
,
highlightReplaceRange
:
true
,
filterGraceful
:
true
,
filterGraceful
:
true
,
snippetsPreventQuickSuggestions
:
true
,
snippetsPreventQuickSuggestions
:
true
,
localityBonus
:
false
,
localityBonus
:
false
,
...
@@ -2527,6 +2532,11 @@ class EditorSuggest extends BaseEditorOption<EditorOption.suggest, InternalSugge
...
@@ -2527,6 +2532,11 @@ class EditorSuggest extends BaseEditorOption<EditorOption.suggest, InternalSugge
default
:
defaults
.
overwriteOnAccept
,
default
:
defaults
.
overwriteOnAccept
,
description
:
nls
.
localize
(
'
suggest.overwriteOnAccept
'
,
"
Controls whether words are overwritten when accepting completions.
"
)
description
:
nls
.
localize
(
'
suggest.overwriteOnAccept
'
,
"
Controls whether words are overwritten when accepting completions.
"
)
},
},
'
editor.suggest.highlightReplaceRange
'
:
{
type
:
'
boolean
'
,
default
:
defaults
.
highlightReplaceRange
,
description
:
nls
.
localize
(
'
suggest.highlightReplaceRange
'
,
"
Controls whether the editor highlights what text suggestions will replace.
"
)
},
'
editor.suggest.filterGraceful
'
:
{
'
editor.suggest.filterGraceful
'
:
{
type
:
'
boolean
'
,
type
:
'
boolean
'
,
default
:
defaults
.
filterGraceful
,
default
:
defaults
.
filterGraceful
,
...
@@ -2704,6 +2714,7 @@ class EditorSuggest extends BaseEditorOption<EditorOption.suggest, InternalSugge
...
@@ -2704,6 +2714,7 @@ class EditorSuggest extends BaseEditorOption<EditorOption.suggest, InternalSugge
const
input
=
_input
as
ISuggestOptions
;
const
input
=
_input
as
ISuggestOptions
;
return
{
return
{
overwriteOnAccept
:
EditorBooleanOption
.
boolean
(
input
.
overwriteOnAccept
,
this
.
defaultValue
.
overwriteOnAccept
),
overwriteOnAccept
:
EditorBooleanOption
.
boolean
(
input
.
overwriteOnAccept
,
this
.
defaultValue
.
overwriteOnAccept
),
highlightReplaceRange
:
EditorBooleanOption
.
boolean
(
input
.
highlightReplaceRange
,
this
.
defaultValue
.
highlightReplaceRange
),
filterGraceful
:
EditorBooleanOption
.
boolean
(
input
.
filterGraceful
,
this
.
defaultValue
.
filterGraceful
),
filterGraceful
:
EditorBooleanOption
.
boolean
(
input
.
filterGraceful
,
this
.
defaultValue
.
filterGraceful
),
snippetsPreventQuickSuggestions
:
EditorBooleanOption
.
boolean
(
input
.
snippetsPreventQuickSuggestions
,
this
.
defaultValue
.
filterGraceful
),
snippetsPreventQuickSuggestions
:
EditorBooleanOption
.
boolean
(
input
.
snippetsPreventQuickSuggestions
,
this
.
defaultValue
.
filterGraceful
),
localityBonus
:
EditorBooleanOption
.
boolean
(
input
.
localityBonus
,
this
.
defaultValue
.
localityBonus
),
localityBonus
:
EditorBooleanOption
.
boolean
(
input
.
localityBonus
,
this
.
defaultValue
.
localityBonus
),
...
...
src/vs/editor/contrib/suggest/suggestController.ts
浏览文件 @
0f6df630
...
@@ -31,12 +31,13 @@ import { WordContextKey } from 'vs/editor/contrib/suggest/wordContextKey';
...
@@ -31,12 +31,13 @@ import { WordContextKey } from 'vs/editor/contrib/suggest/wordContextKey';
import
{
Event
}
from
'
vs/base/common/event
'
;
import
{
Event
}
from
'
vs/base/common/event
'
;
import
{
IEditorWorkerService
}
from
'
vs/editor/common/services/editorWorkerService
'
;
import
{
IEditorWorkerService
}
from
'
vs/editor/common/services/editorWorkerService
'
;
import
{
IdleValue
}
from
'
vs/base/common/async
'
;
import
{
IdleValue
}
from
'
vs/base/common/async
'
;
import
{
isObject
}
from
'
vs/base/common/types
'
;
import
{
isObject
,
assertType
}
from
'
vs/base/common/types
'
;
import
{
CommitCharacterController
}
from
'
./suggestCommitCharacters
'
;
import
{
CommitCharacterController
}
from
'
./suggestCommitCharacters
'
;
import
{
IPosition
}
from
'
vs/editor/common/core/position
'
;
import
{
IPosition
}
from
'
vs/editor/common/core/position
'
;
import
{
TrackedRangeStickiness
,
ITextModel
}
from
'
vs/editor/common/model
'
;
import
{
TrackedRangeStickiness
,
ITextModel
}
from
'
vs/editor/common/model
'
;
import
{
EditorOption
}
from
'
vs/editor/common/config/editorOptions
'
;
import
{
EditorOption
}
from
'
vs/editor/common/config/editorOptions
'
;
import
*
as
platform
from
'
vs/base/common/platform
'
;
import
*
as
platform
from
'
vs/base/common/platform
'
;
import
{
SuggestRangeHighlighter
}
from
'
vs/editor/contrib/suggest/suggestRangeHighlighter
'
;
/**
/**
* Stop suggest widget from disappearing when clicking into other areas
* Stop suggest widget from disappearing when clicking into other areas
...
@@ -101,33 +102,36 @@ export class SuggestController implements IEditorContribution {
...
@@ -101,33 +102,36 @@ export class SuggestController implements IEditorContribution {
return
editor
.
getContribution
<
SuggestController
>
(
SuggestController
.
ID
);
return
editor
.
getContribution
<
SuggestController
>
(
SuggestController
.
ID
);
}
}
private
readonly
_model
:
SuggestModel
;
readonly
editor
:
ICodeEditor
;
private
readonly
_widget
:
IdleValue
<
SuggestWidget
>
;
readonly
model
:
SuggestModel
;
readonly
widget
:
IdleValue
<
SuggestWidget
>
;
private
readonly
_alternatives
:
IdleValue
<
SuggestAlternatives
>
;
private
readonly
_alternatives
:
IdleValue
<
SuggestAlternatives
>
;
private
readonly
_lineSuffix
=
new
MutableDisposable
<
LineSuffix
>
();
private
readonly
_lineSuffix
=
new
MutableDisposable
<
LineSuffix
>
();
private
readonly
_toDispose
=
new
DisposableStore
();
private
readonly
_toDispose
=
new
DisposableStore
();
constructor
(
constructor
(
private
_
editor
:
ICodeEditor
,
editor
:
ICodeEditor
,
@
IEditorWorkerService
editorWorker
:
IEditorWorkerService
,
@
IEditorWorkerService
editorWorker
:
IEditorWorkerService
,
@
ISuggestMemoryService
private
readonly
_memoryService
:
ISuggestMemoryService
,
@
ISuggestMemoryService
private
readonly
_memoryService
:
ISuggestMemoryService
,
@
ICommandService
private
readonly
_commandService
:
ICommandService
,
@
ICommandService
private
readonly
_commandService
:
ICommandService
,
@
IContextKeyService
private
readonly
_contextKeyService
:
IContextKeyService
,
@
IContextKeyService
private
readonly
_contextKeyService
:
IContextKeyService
,
@
IInstantiationService
private
readonly
_instantiationService
:
IInstantiationService
,
@
IInstantiationService
private
readonly
_instantiationService
:
IInstantiationService
,
)
{
)
{
this
.
_model
=
new
SuggestModel
(
this
.
_editor
,
editorWorker
);
this
.
editor
=
editor
;
this
.
model
=
new
SuggestModel
(
this
.
editor
,
editorWorker
);
this
.
_
widget
=
new
IdleValue
(()
=>
{
this
.
widget
=
new
IdleValue
(()
=>
{
const
widget
=
this
.
_instantiationService
.
createInstance
(
SuggestWidget
,
this
.
_
editor
);
const
widget
=
this
.
_instantiationService
.
createInstance
(
SuggestWidget
,
this
.
editor
);
this
.
_toDispose
.
add
(
widget
);
this
.
_toDispose
.
add
(
widget
);
this
.
_toDispose
.
add
(
widget
.
onDidSelect
(
item
=>
this
.
_insertSuggestion
(
item
,
0
),
this
));
this
.
_toDispose
.
add
(
widget
.
onDidSelect
(
item
=>
this
.
_insertSuggestion
(
item
,
0
),
this
));
// Wire up logic to accept a suggestion on certain characters
// Wire up logic to accept a suggestion on certain characters
const
commitCharacterController
=
new
CommitCharacterController
(
this
.
_
editor
,
widget
,
item
=>
this
.
_insertSuggestion
(
item
,
InsertFlags
.
NoAfterUndoStop
));
const
commitCharacterController
=
new
CommitCharacterController
(
this
.
editor
,
widget
,
item
=>
this
.
_insertSuggestion
(
item
,
InsertFlags
.
NoAfterUndoStop
));
this
.
_toDispose
.
add
(
commitCharacterController
);
this
.
_toDispose
.
add
(
commitCharacterController
);
this
.
_toDispose
.
add
(
this
.
_
model
.
onDidSuggest
(
e
=>
{
this
.
_toDispose
.
add
(
this
.
model
.
onDidSuggest
(
e
=>
{
if
(
e
.
completionModel
.
items
.
length
===
0
)
{
if
(
e
.
completionModel
.
items
.
length
===
0
)
{
commitCharacterController
.
reset
();
commitCharacterController
.
reset
();
}
}
...
@@ -137,19 +141,19 @@ export class SuggestController implements IEditorContribution {
...
@@ -137,19 +141,19 @@ export class SuggestController implements IEditorContribution {
let
makesTextEdit
=
SuggestContext
.
MakesTextEdit
.
bindTo
(
this
.
_contextKeyService
);
let
makesTextEdit
=
SuggestContext
.
MakesTextEdit
.
bindTo
(
this
.
_contextKeyService
);
this
.
_toDispose
.
add
(
widget
.
onDidFocus
(({
item
})
=>
{
this
.
_toDispose
.
add
(
widget
.
onDidFocus
(({
item
})
=>
{
const
position
=
this
.
_
editor
.
getPosition
()
!
;
const
position
=
this
.
editor
.
getPosition
()
!
;
const
startColumn
=
item
.
editStart
.
column
;
const
startColumn
=
item
.
editStart
.
column
;
const
endColumn
=
position
.
column
;
const
endColumn
=
position
.
column
;
let
value
=
true
;
let
value
=
true
;
if
(
if
(
this
.
_
editor
.
getOption
(
EditorOption
.
acceptSuggestionOnEnter
)
===
'
smart
'
this
.
editor
.
getOption
(
EditorOption
.
acceptSuggestionOnEnter
)
===
'
smart
'
&&
this
.
_
model
.
state
===
State
.
Auto
&&
this
.
model
.
state
===
State
.
Auto
&&
!
item
.
completion
.
command
&&
!
item
.
completion
.
command
&&
!
item
.
completion
.
additionalTextEdits
&&
!
item
.
completion
.
additionalTextEdits
&&
!
(
item
.
completion
.
insertTextRules
!
&
CompletionItemInsertTextRule
.
InsertAsSnippet
)
&&
!
(
item
.
completion
.
insertTextRules
!
&
CompletionItemInsertTextRule
.
InsertAsSnippet
)
&&
endColumn
-
startColumn
===
item
.
completion
.
insertText
.
length
&&
endColumn
-
startColumn
===
item
.
completion
.
insertText
.
length
)
{
)
{
const
oldText
=
this
.
_
editor
.
getModel
()
!
.
getValueInRange
({
const
oldText
=
this
.
editor
.
getModel
()
!
.
getValueInRange
({
startLineNumber
:
position
.
lineNumber
,
startLineNumber
:
position
.
lineNumber
,
startColumn
,
startColumn
,
endLineNumber
:
position
.
lineNumber
,
endLineNumber
:
position
.
lineNumber
,
...
@@ -161,38 +165,40 @@ export class SuggestController implements IEditorContribution {
...
@@ -161,38 +165,40 @@ export class SuggestController implements IEditorContribution {
}));
}));
this
.
_toDispose
.
add
(
toDisposable
(()
=>
makesTextEdit
.
reset
()));
this
.
_toDispose
.
add
(
toDisposable
(()
=>
makesTextEdit
.
reset
()));
return
widget
;
return
widget
;
});
});
this
.
_alternatives
=
new
IdleValue
(()
=>
{
this
.
_alternatives
=
new
IdleValue
(()
=>
{
return
this
.
_toDispose
.
add
(
new
SuggestAlternatives
(
this
.
_
editor
,
this
.
_contextKeyService
));
return
this
.
_toDispose
.
add
(
new
SuggestAlternatives
(
this
.
editor
,
this
.
_contextKeyService
));
});
});
this
.
_toDispose
.
add
(
_instantiationService
.
createInstance
(
WordContextKey
,
_
editor
));
this
.
_toDispose
.
add
(
_instantiationService
.
createInstance
(
WordContextKey
,
editor
));
this
.
_toDispose
.
add
(
this
.
_
model
.
onDidTrigger
(
e
=>
{
this
.
_toDispose
.
add
(
this
.
model
.
onDidTrigger
(
e
=>
{
this
.
_
widget
.
getValue
().
showTriggered
(
e
.
auto
,
e
.
shy
?
250
:
50
);
this
.
widget
.
getValue
().
showTriggered
(
e
.
auto
,
e
.
shy
?
250
:
50
);
this
.
_lineSuffix
.
value
=
new
LineSuffix
(
this
.
_
editor
.
getModel
()
!
,
e
.
position
);
this
.
_lineSuffix
.
value
=
new
LineSuffix
(
this
.
editor
.
getModel
()
!
,
e
.
position
);
}));
}));
this
.
_toDispose
.
add
(
this
.
_
model
.
onDidSuggest
(
e
=>
{
this
.
_toDispose
.
add
(
this
.
model
.
onDidSuggest
(
e
=>
{
if
(
!
e
.
shy
)
{
if
(
!
e
.
shy
)
{
let
index
=
this
.
_memoryService
.
select
(
this
.
_editor
.
getModel
()
!
,
this
.
_
editor
.
getPosition
()
!
,
e
.
completionModel
.
items
);
let
index
=
this
.
_memoryService
.
select
(
this
.
editor
.
getModel
()
!
,
this
.
editor
.
getPosition
()
!
,
e
.
completionModel
.
items
);
this
.
_
widget
.
getValue
().
showSuggestions
(
e
.
completionModel
,
index
,
e
.
isFrozen
,
e
.
auto
);
this
.
widget
.
getValue
().
showSuggestions
(
e
.
completionModel
,
index
,
e
.
isFrozen
,
e
.
auto
);
}
}
}));
}));
this
.
_toDispose
.
add
(
this
.
_
model
.
onDidCancel
(
e
=>
{
this
.
_toDispose
.
add
(
this
.
model
.
onDidCancel
(
e
=>
{
if
(
!
e
.
retrigger
)
{
if
(
!
e
.
retrigger
)
{
this
.
_
widget
.
getValue
().
hideWidget
();
this
.
widget
.
getValue
().
hideWidget
();
}
}
}));
}));
this
.
_toDispose
.
add
(
this
.
_
editor
.
onDidBlurEditorWidget
(()
=>
{
this
.
_toDispose
.
add
(
this
.
editor
.
onDidBlurEditorWidget
(()
=>
{
if
(
!
_sticky
)
{
if
(
!
_sticky
)
{
this
.
_
model
.
cancel
();
this
.
model
.
cancel
();
this
.
_
model
.
clear
();
this
.
model
.
clear
();
}
}
}));
}));
this
.
_toDispose
.
add
(
this
.
_
widget
.
getValue
().
onDetailsKeyDown
(
e
=>
{
this
.
_toDispose
.
add
(
this
.
widget
.
getValue
().
onDetailsKeyDown
(
e
=>
{
// cmd + c on macOS, ctrl + c on Win / Linux
// cmd + c on macOS, ctrl + c on Win / Linux
if
(
if
(
e
.
toKeybinding
().
equals
(
new
SimpleKeybinding
(
true
,
false
,
false
,
false
,
KeyCode
.
KEY_C
))
||
e
.
toKeybinding
().
equals
(
new
SimpleKeybinding
(
true
,
false
,
false
,
false
,
KeyCode
.
KEY_C
))
||
...
@@ -203,25 +209,28 @@ export class SuggestController implements IEditorContribution {
...
@@ -203,25 +209,28 @@ export class SuggestController implements IEditorContribution {
}
}
if
(
!
e
.
toKeybinding
().
isModifierKey
())
{
if
(
!
e
.
toKeybinding
().
isModifierKey
())
{
this
.
_
editor
.
focus
();
this
.
editor
.
focus
();
}
}
}));
}));
// Manage the acceptSuggestionsOnEnter context key
// Manage the acceptSuggestionsOnEnter context key
let
acceptSuggestionsOnEnter
=
SuggestContext
.
AcceptSuggestionsOnEnter
.
bindTo
(
_contextKeyService
);
let
acceptSuggestionsOnEnter
=
SuggestContext
.
AcceptSuggestionsOnEnter
.
bindTo
(
_contextKeyService
);
let
updateFromConfig
=
()
=>
{
let
updateFromConfig
=
()
=>
{
const
acceptSuggestionOnEnter
=
this
.
_
editor
.
getOption
(
EditorOption
.
acceptSuggestionOnEnter
);
const
acceptSuggestionOnEnter
=
this
.
editor
.
getOption
(
EditorOption
.
acceptSuggestionOnEnter
);
acceptSuggestionsOnEnter
.
set
(
acceptSuggestionOnEnter
===
'
on
'
||
acceptSuggestionOnEnter
===
'
smart
'
);
acceptSuggestionsOnEnter
.
set
(
acceptSuggestionOnEnter
===
'
on
'
||
acceptSuggestionOnEnter
===
'
smart
'
);
};
};
this
.
_toDispose
.
add
(
this
.
_
editor
.
onDidChangeConfiguration
(()
=>
updateFromConfig
()));
this
.
_toDispose
.
add
(
this
.
editor
.
onDidChangeConfiguration
(()
=>
updateFromConfig
()));
updateFromConfig
();
updateFromConfig
();
// create range highlighter
this
.
_toDispose
.
add
(
new
SuggestRangeHighlighter
(
this
));
}
}
dispose
():
void
{
dispose
():
void
{
this
.
_alternatives
.
dispose
();
this
.
_alternatives
.
dispose
();
this
.
_toDispose
.
dispose
();
this
.
_toDispose
.
dispose
();
this
.
_
widget
.
dispose
();
this
.
widget
.
dispose
();
this
.
_
model
.
dispose
();
this
.
model
.
dispose
();
this
.
_lineSuffix
.
dispose
();
this
.
_lineSuffix
.
dispose
();
}
}
...
@@ -231,32 +240,31 @@ export class SuggestController implements IEditorContribution {
...
@@ -231,32 +240,31 @@ export class SuggestController implements IEditorContribution {
):
void
{
):
void
{
if
(
!
event
||
!
event
.
item
)
{
if
(
!
event
||
!
event
.
item
)
{
this
.
_alternatives
.
getValue
().
reset
();
this
.
_alternatives
.
getValue
().
reset
();
this
.
_
model
.
cancel
();
this
.
model
.
cancel
();
this
.
_
model
.
clear
();
this
.
model
.
clear
();
return
;
return
;
}
}
if
(
!
this
.
_
editor
.
hasModel
())
{
if
(
!
this
.
editor
.
hasModel
())
{
return
;
return
;
}
}
const
model
=
this
.
_
editor
.
getModel
();
const
model
=
this
.
editor
.
getModel
();
const
modelVersionNow
=
model
.
getAlternativeVersionId
();
const
modelVersionNow
=
model
.
getAlternativeVersionId
();
const
{
item
}
=
event
;
const
{
item
}
=
event
;
const
{
completion
:
suggestion
,
position
}
=
item
;
const
{
completion
:
suggestion
}
=
item
;
const
columnDelta
=
this
.
_editor
.
getPosition
().
column
-
position
.
column
;
// pushing undo stops *before* additional text edits and
// pushing undo stops *before* additional text edits and
// *after* the main edit
// *after* the main edit
if
(
!
(
flags
&
InsertFlags
.
NoBeforeUndoStop
))
{
if
(
!
(
flags
&
InsertFlags
.
NoBeforeUndoStop
))
{
this
.
_
editor
.
pushUndoStop
();
this
.
editor
.
pushUndoStop
();
}
}
if
(
Array
.
isArray
(
suggestion
.
additionalTextEdits
))
{
if
(
Array
.
isArray
(
suggestion
.
additionalTextEdits
))
{
this
.
_
editor
.
executeEdits
(
'
suggestController.additionalTextEdits
'
,
suggestion
.
additionalTextEdits
.
map
(
edit
=>
EditOperation
.
replace
(
Range
.
lift
(
edit
.
range
),
edit
.
text
)));
this
.
editor
.
executeEdits
(
'
suggestController.additionalTextEdits
'
,
suggestion
.
additionalTextEdits
.
map
(
edit
=>
EditOperation
.
replace
(
Range
.
lift
(
edit
.
range
),
edit
.
text
)));
}
}
// keep item in memory
// keep item in memory
this
.
_memoryService
.
memorize
(
model
,
this
.
_
editor
.
getPosition
(),
item
);
this
.
_memoryService
.
memorize
(
model
,
this
.
editor
.
getPosition
(),
item
);
let
{
insertText
}
=
suggestion
;
let
{
insertText
}
=
suggestion
;
if
(
!
(
suggestion
.
insertTextRules
!
&
CompletionItemInsertTextRule
.
InsertAsSnippet
))
{
if
(
!
(
suggestion
.
insertTextRules
!
&
CompletionItemInsertTextRule
.
InsertAsSnippet
))
{
...
@@ -264,40 +272,38 @@ export class SuggestController implements IEditorContribution {
...
@@ -264,40 +272,38 @@ export class SuggestController implements IEditorContribution {
}
}
const
overwriteConfig
=
flags
&
InsertFlags
.
AlternativeOverwriteConfig
const
overwriteConfig
=
flags
&
InsertFlags
.
AlternativeOverwriteConfig
?
!
this
.
_
editor
.
getOption
(
EditorOption
.
suggest
).
overwriteOnAccept
?
!
this
.
editor
.
getOption
(
EditorOption
.
suggest
).
overwriteOnAccept
:
this
.
_
editor
.
getOption
(
EditorOption
.
suggest
).
overwriteOnAccept
;
:
this
.
editor
.
getOption
(
EditorOption
.
suggest
).
overwriteOnAccept
;
const
overwriteBefore
=
position
.
column
-
item
.
editStart
.
column
;
const
info
=
this
.
getOverwriteInfo
(
item
,
overwriteConfig
);
const
overwriteAfter
=
(
overwriteConfig
?
item
.
editReplaceEnd
.
column
:
item
.
editInsertEnd
.
column
)
-
position
.
column
;
const
suffixDelta
=
this
.
_lineSuffix
.
value
?
this
.
_lineSuffix
.
value
.
delta
(
this
.
_editor
.
getPosition
())
:
0
;
SnippetController2
.
get
(
this
.
_
editor
).
insert
(
insertText
,
{
SnippetController2
.
get
(
this
.
editor
).
insert
(
insertText
,
{
overwriteBefore
:
overwriteBefore
+
columnDelta
,
overwriteBefore
:
info
.
overwriteBefore
,
overwriteAfter
:
overwriteAfter
+
suffixDelta
,
overwriteAfter
:
info
.
overwriteAfter
,
undoStopBefore
:
false
,
undoStopBefore
:
false
,
undoStopAfter
:
false
,
undoStopAfter
:
false
,
adjustWhitespace
:
!
(
suggestion
.
insertTextRules
!
&
CompletionItemInsertTextRule
.
KeepWhitespace
)
adjustWhitespace
:
!
(
suggestion
.
insertTextRules
!
&
CompletionItemInsertTextRule
.
KeepWhitespace
)
});
});
if
(
!
(
flags
&
InsertFlags
.
NoAfterUndoStop
))
{
if
(
!
(
flags
&
InsertFlags
.
NoAfterUndoStop
))
{
this
.
_
editor
.
pushUndoStop
();
this
.
editor
.
pushUndoStop
();
}
}
if
(
!
suggestion
.
command
)
{
if
(
!
suggestion
.
command
)
{
// done
// done
this
.
_
model
.
cancel
();
this
.
model
.
cancel
();
this
.
_
model
.
clear
();
this
.
model
.
clear
();
}
else
if
(
suggestion
.
command
.
id
===
TriggerSuggestAction
.
id
)
{
}
else
if
(
suggestion
.
command
.
id
===
TriggerSuggestAction
.
id
)
{
// retigger
// retigger
this
.
_
model
.
trigger
({
auto
:
true
,
shy
:
false
},
true
);
this
.
model
.
trigger
({
auto
:
true
,
shy
:
false
},
true
);
}
else
{
}
else
{
// exec command, done
// exec command, done
this
.
_commandService
.
executeCommand
(
suggestion
.
command
.
id
,
...(
suggestion
.
command
.
arguments
?
[...
suggestion
.
command
.
arguments
]
:
[]))
this
.
_commandService
.
executeCommand
(
suggestion
.
command
.
id
,
...(
suggestion
.
command
.
arguments
?
[...
suggestion
.
command
.
arguments
]
:
[]))
.
catch
(
onUnexpectedError
)
.
catch
(
onUnexpectedError
)
.
finally
(()
=>
this
.
_
model
.
clear
());
// <- clear only now, keep commands alive
.
finally
(()
=>
this
.
model
.
clear
());
// <- clear only now, keep commands alive
this
.
_
model
.
cancel
();
this
.
model
.
cancel
();
}
}
if
(
flags
&
InsertFlags
.
KeepAlternativeSuggestions
)
{
if
(
flags
&
InsertFlags
.
KeepAlternativeSuggestions
)
{
...
@@ -321,6 +327,20 @@ export class SuggestController implements IEditorContribution {
...
@@ -321,6 +327,20 @@ export class SuggestController implements IEditorContribution {
this
.
_alertCompletionItem
(
event
.
item
);
this
.
_alertCompletionItem
(
event
.
item
);
}
}
getOverwriteInfo
(
item
:
CompletionItem
,
overwriteOnAccept
:
boolean
):
{
overwriteBefore
:
number
,
overwriteAfter
:
number
}
{
assertType
(
this
.
editor
.
hasModel
());
const
overwriteBefore
=
item
.
position
.
column
-
item
.
editStart
.
column
;
const
overwriteAfter
=
(
overwriteOnAccept
?
item
.
editReplaceEnd
.
column
:
item
.
editInsertEnd
.
column
)
-
item
.
position
.
column
;
const
columnDelta
=
this
.
editor
.
getPosition
().
column
-
item
.
position
.
column
;
const
suffixDelta
=
this
.
_lineSuffix
.
value
?
this
.
_lineSuffix
.
value
.
delta
(
this
.
editor
.
getPosition
())
:
0
;
return
{
overwriteBefore
:
overwriteBefore
+
columnDelta
,
overwriteAfter
:
overwriteAfter
+
suffixDelta
};
}
private
_alertCompletionItem
({
completion
:
suggestion
}:
CompletionItem
):
void
{
private
_alertCompletionItem
({
completion
:
suggestion
}:
CompletionItem
):
void
{
if
(
isNonEmptyArray
(
suggestion
.
additionalTextEdits
))
{
if
(
isNonEmptyArray
(
suggestion
.
additionalTextEdits
))
{
let
msg
=
nls
.
localize
(
'
arai.alert.snippet
'
,
"
Accepting '{0}' made {1} additional edits
"
,
suggestion
.
label
,
suggestion
.
additionalTextEdits
.
length
);
let
msg
=
nls
.
localize
(
'
arai.alert.snippet
'
,
"
Accepting '{0}' made {1} additional edits
"
,
suggestion
.
label
,
suggestion
.
additionalTextEdits
.
length
);
...
@@ -329,22 +349,22 @@ export class SuggestController implements IEditorContribution {
...
@@ -329,22 +349,22 @@ export class SuggestController implements IEditorContribution {
}
}
triggerSuggest
(
onlyFrom
?:
Set
<
CompletionItemProvider
>
):
void
{
triggerSuggest
(
onlyFrom
?:
Set
<
CompletionItemProvider
>
):
void
{
if
(
this
.
_
editor
.
hasModel
())
{
if
(
this
.
editor
.
hasModel
())
{
this
.
_
model
.
trigger
({
auto
:
false
,
shy
:
false
},
false
,
onlyFrom
);
this
.
model
.
trigger
({
auto
:
false
,
shy
:
false
},
false
,
onlyFrom
);
this
.
_editor
.
revealLine
(
this
.
_
editor
.
getPosition
().
lineNumber
,
ScrollType
.
Smooth
);
this
.
editor
.
revealLine
(
this
.
editor
.
getPosition
().
lineNumber
,
ScrollType
.
Smooth
);
this
.
_
editor
.
focus
();
this
.
editor
.
focus
();
}
}
}
}
triggerSuggestAndAcceptBest
(
arg
:
{
fallback
:
string
}):
void
{
triggerSuggestAndAcceptBest
(
arg
:
{
fallback
:
string
}):
void
{
if
(
!
this
.
_
editor
.
hasModel
())
{
if
(
!
this
.
editor
.
hasModel
())
{
return
;
return
;
}
}
const
positionNow
=
this
.
_
editor
.
getPosition
();
const
positionNow
=
this
.
editor
.
getPosition
();
const
fallback
=
()
=>
{
const
fallback
=
()
=>
{
if
(
positionNow
.
equals
(
this
.
_
editor
.
getPosition
()
!
))
{
if
(
positionNow
.
equals
(
this
.
editor
.
getPosition
()
!
))
{
this
.
_commandService
.
executeCommand
(
arg
.
fallback
);
this
.
_commandService
.
executeCommand
(
arg
.
fallback
);
}
}
};
};
...
@@ -354,14 +374,14 @@ export class SuggestController implements IEditorContribution {
...
@@ -354,14 +374,14 @@ export class SuggestController implements IEditorContribution {
// snippet, other editor -> makes edit
// snippet, other editor -> makes edit
return
true
;
return
true
;
}
}
const
position
=
this
.
_
editor
.
getPosition
()
!
;
const
position
=
this
.
editor
.
getPosition
()
!
;
const
startColumn
=
item
.
editStart
.
column
;
const
startColumn
=
item
.
editStart
.
column
;
const
endColumn
=
position
.
column
;
const
endColumn
=
position
.
column
;
if
(
endColumn
-
startColumn
!==
item
.
completion
.
insertText
.
length
)
{
if
(
endColumn
-
startColumn
!==
item
.
completion
.
insertText
.
length
)
{
// unequal lengths -> makes edit
// unequal lengths -> makes edit
return
true
;
return
true
;
}
}
const
textNow
=
this
.
_
editor
.
getModel
()
!
.
getValueInRange
({
const
textNow
=
this
.
editor
.
getModel
()
!
.
getValueInRange
({
startLineNumber
:
position
.
lineNumber
,
startLineNumber
:
position
.
lineNumber
,
startColumn
,
startColumn
,
endLineNumber
:
position
.
lineNumber
,
endLineNumber
:
position
.
lineNumber
,
...
@@ -371,41 +391,41 @@ export class SuggestController implements IEditorContribution {
...
@@ -371,41 +391,41 @@ export class SuggestController implements IEditorContribution {
return
textNow
!==
item
.
completion
.
insertText
;
return
textNow
!==
item
.
completion
.
insertText
;
};
};
Event
.
once
(
this
.
_
model
.
onDidTrigger
)(
_
=>
{
Event
.
once
(
this
.
model
.
onDidTrigger
)(
_
=>
{
// wait for trigger because only then the cancel-event is trustworthy
// wait for trigger because only then the cancel-event is trustworthy
let
listener
:
IDisposable
[]
=
[];
let
listener
:
IDisposable
[]
=
[];
Event
.
any
<
any
>
(
this
.
_model
.
onDidTrigger
,
this
.
_
model
.
onDidCancel
)(()
=>
{
Event
.
any
<
any
>
(
this
.
model
.
onDidTrigger
,
this
.
model
.
onDidCancel
)(()
=>
{
// retrigger or cancel -> try to type default text
// retrigger or cancel -> try to type default text
dispose
(
listener
);
dispose
(
listener
);
fallback
();
fallback
();
},
undefined
,
listener
);
},
undefined
,
listener
);
this
.
_
model
.
onDidSuggest
(({
completionModel
})
=>
{
this
.
model
.
onDidSuggest
(({
completionModel
})
=>
{
dispose
(
listener
);
dispose
(
listener
);
if
(
completionModel
.
items
.
length
===
0
)
{
if
(
completionModel
.
items
.
length
===
0
)
{
fallback
();
fallback
();
return
;
return
;
}
}
const
index
=
this
.
_memoryService
.
select
(
this
.
_editor
.
getModel
()
!
,
this
.
_
editor
.
getPosition
()
!
,
completionModel
.
items
);
const
index
=
this
.
_memoryService
.
select
(
this
.
editor
.
getModel
()
!
,
this
.
editor
.
getPosition
()
!
,
completionModel
.
items
);
const
item
=
completionModel
.
items
[
index
];
const
item
=
completionModel
.
items
[
index
];
if
(
!
makesTextEdit
(
item
))
{
if
(
!
makesTextEdit
(
item
))
{
fallback
();
fallback
();
return
;
return
;
}
}
this
.
_
editor
.
pushUndoStop
();
this
.
editor
.
pushUndoStop
();
this
.
_insertSuggestion
({
index
,
item
,
model
:
completionModel
},
InsertFlags
.
KeepAlternativeSuggestions
|
InsertFlags
.
NoBeforeUndoStop
|
InsertFlags
.
NoAfterUndoStop
);
this
.
_insertSuggestion
({
index
,
item
,
model
:
completionModel
},
InsertFlags
.
KeepAlternativeSuggestions
|
InsertFlags
.
NoBeforeUndoStop
|
InsertFlags
.
NoAfterUndoStop
);
},
undefined
,
listener
);
},
undefined
,
listener
);
});
});
this
.
_
model
.
trigger
({
auto
:
false
,
shy
:
true
});
this
.
model
.
trigger
({
auto
:
false
,
shy
:
true
});
this
.
_
editor
.
revealLine
(
positionNow
.
lineNumber
,
ScrollType
.
Smooth
);
this
.
editor
.
revealLine
(
positionNow
.
lineNumber
,
ScrollType
.
Smooth
);
this
.
_
editor
.
focus
();
this
.
editor
.
focus
();
}
}
acceptSelectedSuggestion
(
keepAlternativeSuggestions
:
boolean
,
alternativeOverwriteConfig
:
boolean
):
void
{
acceptSelectedSuggestion
(
keepAlternativeSuggestions
:
boolean
,
alternativeOverwriteConfig
:
boolean
):
void
{
const
item
=
this
.
_
widget
.
getValue
().
getFocusedItem
();
const
item
=
this
.
widget
.
getValue
().
getFocusedItem
();
let
flags
=
0
;
let
flags
=
0
;
if
(
keepAlternativeSuggestions
)
{
if
(
keepAlternativeSuggestions
)
{
flags
|=
InsertFlags
.
KeepAlternativeSuggestions
;
flags
|=
InsertFlags
.
KeepAlternativeSuggestions
;
...
@@ -425,45 +445,45 @@ export class SuggestController implements IEditorContribution {
...
@@ -425,45 +445,45 @@ export class SuggestController implements IEditorContribution {
}
}
cancelSuggestWidget
():
void
{
cancelSuggestWidget
():
void
{
this
.
_
model
.
cancel
();
this
.
model
.
cancel
();
this
.
_
model
.
clear
();
this
.
model
.
clear
();
this
.
_
widget
.
getValue
().
hideWidget
();
this
.
widget
.
getValue
().
hideWidget
();
}
}
selectNextSuggestion
():
void
{
selectNextSuggestion
():
void
{
this
.
_
widget
.
getValue
().
selectNext
();
this
.
widget
.
getValue
().
selectNext
();
}
}
selectNextPageSuggestion
():
void
{
selectNextPageSuggestion
():
void
{
this
.
_
widget
.
getValue
().
selectNextPage
();
this
.
widget
.
getValue
().
selectNextPage
();
}
}
selectLastSuggestion
():
void
{
selectLastSuggestion
():
void
{
this
.
_
widget
.
getValue
().
selectLast
();
this
.
widget
.
getValue
().
selectLast
();
}
}
selectPrevSuggestion
():
void
{
selectPrevSuggestion
():
void
{
this
.
_
widget
.
getValue
().
selectPrevious
();
this
.
widget
.
getValue
().
selectPrevious
();
}
}
selectPrevPageSuggestion
():
void
{
selectPrevPageSuggestion
():
void
{
this
.
_
widget
.
getValue
().
selectPreviousPage
();
this
.
widget
.
getValue
().
selectPreviousPage
();
}
}
selectFirstSuggestion
():
void
{
selectFirstSuggestion
():
void
{
this
.
_
widget
.
getValue
().
selectFirst
();
this
.
widget
.
getValue
().
selectFirst
();
}
}
toggleSuggestionDetails
():
void
{
toggleSuggestionDetails
():
void
{
this
.
_
widget
.
getValue
().
toggleDetails
();
this
.
widget
.
getValue
().
toggleDetails
();
}
}
toggleExplainMode
():
void
{
toggleExplainMode
():
void
{
this
.
_
widget
.
getValue
().
toggleExplainMode
();
this
.
widget
.
getValue
().
toggleExplainMode
();
}
}
toggleSuggestionFocus
():
void
{
toggleSuggestionFocus
():
void
{
this
.
_
widget
.
getValue
().
toggleDetailsFocus
();
this
.
widget
.
getValue
().
toggleDetailsFocus
();
}
}
}
}
...
...
src/vs/editor/contrib/suggest/suggestRangeHighlighter.ts
0 → 100644
浏览文件 @
0f6df630
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
DisposableStore
}
from
'
vs/base/common/lifecycle
'
;
import
{
Range
}
from
'
vs/editor/common/core/range
'
;
import
{
registerThemingParticipant
}
from
'
vs/platform/theme/common/themeService
'
;
import
{
editorSelectionBackground
,
registerColor
,
editorSelectionHighlightBorder
}
from
'
vs/platform/theme/common/colorRegistry
'
;
import
{
EditorOption
}
from
'
vs/editor/common/config/editorOptions
'
;
import
{
CompletionItem
}
from
'
vs/editor/contrib/suggest/suggest
'
;
import
{
TrackedRangeStickiness
}
from
'
vs/editor/common/model
'
;
import
{
SuggestController
}
from
'
vs/editor/contrib/suggest/suggestController
'
;
import
{
localize
}
from
'
vs/nls
'
;
const
suggestReplaceBackgroundColor
=
registerColor
(
'
editor.suggestReplaceBackground
'
,
{
light
:
editorSelectionBackground
,
dark
:
editorSelectionBackground
,
hc
:
editorSelectionBackground
},
localize
(
'
suggestReplaceBackground
'
,
"
Background color of text that suggest will replace.
"
)
);
const
suggestReplaceBorderColor
=
registerColor
(
'
editor.suggestReplaceBorder
'
,
{
light
:
null
,
dark
:
null
,
hc
:
editorSelectionHighlightBorder
},
localize
(
'
suggestReplaceBorder
'
,
"
Border color of text that suggest will replace.
"
)
);
registerThemingParticipant
((
theme
,
collector
)
=>
{
const
suggestReplaceBackground
=
theme
.
getColor
(
suggestReplaceBackgroundColor
);
if
(
suggestReplaceBackground
)
{
collector
.
addRule
(
`.monaco-editor .suggestReplace { background-color:
${
suggestReplaceBackground
}
; }`
);
}
const
suggestReplaceBorder
=
theme
.
getColor
(
suggestReplaceBorderColor
);
if
(
suggestReplaceBorder
)
{
collector
.
addRule
(
`.monaco-editor .suggestReplace { border: 1px
${
theme
.
type
===
'
hc
'
?
'
dotted
'
:
'
solid
'
}
${
suggestReplaceBorder
}
; }`
);
}
});
export
class
SuggestRangeHighlighter
{
private
readonly
_disposables
=
new
DisposableStore
();
private
_decorations
:
string
[]
=
[];
private
_hasWidgetListener
:
boolean
=
false
;
constructor
(
private
readonly
_controller
:
SuggestController
)
{
this
.
_disposables
.
add
(
_controller
.
model
.
onDidSuggest
(
e
=>
{
if
(
!
e
.
shy
)
{
const
widget
=
this
.
_controller
.
widget
.
getValue
();
const
focused
=
widget
.
getFocusedItem
();
if
(
focused
)
{
this
.
_highlight
(
focused
.
item
);
}
if
(
!
this
.
_hasWidgetListener
)
{
this
.
_hasWidgetListener
=
true
;
widget
.
onDidFocus
(
e
=>
this
.
_highlight
(
e
.
item
),
undefined
,
this
.
_disposables
);
}
}
}));
this
.
_disposables
.
add
(
_controller
.
model
.
onDidCancel
(()
=>
{
this
.
_reset
();
}));
}
dispose
():
void
{
this
.
_reset
();
this
.
_disposables
.
dispose
();
}
private
_reset
():
void
{
this
.
_decorations
=
this
.
_controller
.
editor
.
deltaDecorations
(
this
.
_decorations
,
[]);
}
private
_highlight
(
item
:
CompletionItem
)
{
const
{
overwriteOnAccept
,
highlightReplaceRange
}
=
this
.
_controller
.
editor
.
getOption
(
EditorOption
.
suggest
);
if
(
highlightReplaceRange
)
{
const
info
=
this
.
_controller
.
getOverwriteInfo
(
item
,
overwriteOnAccept
);
const
position
=
this
.
_controller
.
editor
.
getPosition
()
!
;
const
range
=
new
Range
(
position
.
lineNumber
,
position
.
column
-
info
.
overwriteBefore
,
position
.
lineNumber
,
position
.
column
+
info
.
overwriteAfter
);
this
.
_decorations
=
this
.
_controller
.
editor
.
deltaDecorations
(
this
.
_decorations
,
[{
range
,
options
:
{
className
:
'
suggestReplace
'
,
stickiness
:
TrackedRangeStickiness
.
AlwaysGrowsWhenTypingAtEdges
}
}]);
}
}
}
src/vs/editor/contrib/suggest/test/completionModel.test.ts
浏览文件 @
0f6df630
...
@@ -35,6 +35,7 @@ suite('CompletionModel', function () {
...
@@ -35,6 +35,7 @@ suite('CompletionModel', function () {
let
defaultOptions
=
{
let
defaultOptions
=
{
overwriteOnAccept
:
false
,
overwriteOnAccept
:
false
,
highlightReplaceRange
:
true
,
snippetsPreventQuickSuggestions
:
true
,
snippetsPreventQuickSuggestions
:
true
,
filterGraceful
:
true
,
filterGraceful
:
true
,
localityBonus
:
false
,
localityBonus
:
false
,
...
...
src/vs/monaco.d.ts
浏览文件 @
0f6df630
...
@@ -3397,6 +3397,10 @@ declare namespace monaco.editor {
...
@@ -3397,6 +3397,10 @@ declare namespace monaco.editor {
* Overwrite word ends on accept. Default to false.
* Overwrite word ends on accept. Default to false.
*/
*/
overwriteOnAccept
?:
boolean
;
overwriteOnAccept
?:
boolean
;
/**
* Should the editor highlight what text suggest will replace.
*/
highlightReplaceRange
?:
boolean
;
/**
/**
* Enable graceful matching. Defaults to true.
* Enable graceful matching. Defaults to true.
*/
*/
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录