提交 d6b04f3a 编写于 作者: J Johannes Rieken

adding setting 'editor.suggest.overwriteOnAccept' #10266

上级 7e71b7b1
......@@ -2286,6 +2286,10 @@ class EditorScrollbar extends BaseEditorOption<EditorOption.scrollbar, InternalE
* Configuration options for editor suggest widget
*/
export interface ISuggestOptions {
/**
* Overwrite word ends on accept. Default to false.
*/
overwriteOnAccept?: boolean;
/**
* Enable graceful matching. Defaults to true.
*/
......@@ -2322,6 +2326,7 @@ class EditorSuggest extends BaseEditorOption<EditorOption.suggest, InternalSugge
constructor() {
const defaults: InternalSuggestOptions = {
overwriteOnAccept: false,
filterGraceful: true,
snippetsPreventQuickSuggestions: true,
localityBonus: false,
......@@ -2333,6 +2338,11 @@ class EditorSuggest extends BaseEditorOption<EditorOption.suggest, InternalSugge
super(
EditorOption.suggest, 'suggest', defaults,
{
'editor.suggest.overwriteOnAccept': {
type: 'boolean',
default: defaults.overwriteOnAccept,
description: nls.localize('suggest.overwriteOnAccept', "Controls whether words are overwritten when accepting completions.")
},
'editor.suggest.filterGraceful': {
type: 'boolean',
default: defaults.filterGraceful,
......@@ -2505,6 +2515,7 @@ class EditorSuggest extends BaseEditorOption<EditorOption.suggest, InternalSugge
}
const input = _input as ISuggestOptions;
return {
overwriteOnAccept: EditorBooleanOption.boolean(input.overwriteOnAccept, this.defaultValue.overwriteOnAccept),
filterGraceful: EditorBooleanOption.boolean(input.filterGraceful, this.defaultValue.filterGraceful),
snippetsPreventQuickSuggestions: EditorBooleanOption.boolean(input.snippetsPreventQuickSuggestions, this.defaultValue.filterGraceful),
localityBonus: EditorBooleanOption.boolean(input.localityBonus, this.defaultValue.localityBonus),
......
......@@ -86,6 +86,13 @@ class LineSuffix {
}
}
const enum InsertFlags {
NoBeforeUndoStop = 1,
NoAfterUndoStop = 2,
KeepAlternativeSuggestions = 4,
AlternativeOverwriteConfig = 8
}
export class SuggestController implements IEditorContribution {
public static readonly ID: string = 'editor.contrib.suggestController';
......@@ -115,10 +122,10 @@ export class SuggestController implements IEditorContribution {
const widget = this._instantiationService.createInstance(SuggestWidget, this._editor);
this._toDispose.add(widget);
this._toDispose.add(widget.onDidSelect(item => this._insertSuggestion(item, false, true, true, true), this));
this._toDispose.add(widget.onDidSelect(item => this._insertSuggestion(item, 0), this));
// Wire up logic to accept a suggestion on certain characters
const commitCharacterController = new CommitCharacterController(this._editor, widget, item => this._insertSuggestion(item, false, true, false, true));
const commitCharacterController = new CommitCharacterController(this._editor, widget, item => this._insertSuggestion(item, InsertFlags.NoAfterUndoStop));
this._toDispose.add(commitCharacterController);
this._toDispose.add(this._model.onDidSuggest(e => {
if (e.completionModel.items.length === 0) {
......@@ -220,9 +227,7 @@ export class SuggestController implements IEditorContribution {
protected _insertSuggestion(
event: ISelectedSuggestion | undefined,
keepAlternativeSuggestions: boolean,
undoStopBefore: boolean, undoStopAfter: boolean,
keepSuffix: boolean
flags: InsertFlags
): void {
if (!event || !event.item) {
this._alternatives.getValue().reset();
......@@ -241,7 +246,7 @@ export class SuggestController implements IEditorContribution {
// pushing undo stops *before* additional text edits and
// *after* the main edit
if (undoStopBefore) {
if (!(flags & InsertFlags.NoBeforeUndoStop)) {
this._editor.pushUndoStop();
}
......@@ -261,7 +266,11 @@ export class SuggestController implements IEditorContribution {
let overwriteAfter = suggestion.range.endColumn - position.column;
let suffixDelta = this._lineSuffix.value ? this._lineSuffix.value.delta(this._editor.getPosition()) : 0;
let word: IWordAtPosition | null;
if (!keepSuffix) {
const overwriteConfig = flags & InsertFlags.AlternativeOverwriteConfig
? !this._editor.getOption(EditorOption.suggest).overwriteOnAccept
: this._editor.getOption(EditorOption.suggest).overwriteOnAccept;
if (!overwriteConfig) {
// don't overwrite anything right of the cursor
overwriteAfter = 0;
......@@ -278,7 +287,7 @@ export class SuggestController implements IEditorContribution {
adjustWhitespace: !(suggestion.insertTextRules! & CompletionItemInsertTextRule.KeepWhitespace)
});
if (undoStopAfter) {
if (!(flags & InsertFlags.NoAfterUndoStop)) {
this._editor.pushUndoStop();
}
......@@ -299,7 +308,7 @@ export class SuggestController implements IEditorContribution {
this._model.cancel();
}
if (keepAlternativeSuggestions) {
if (flags & InsertFlags.KeepAlternativeSuggestions) {
this._alternatives.getValue().set(event, next => {
// this is not so pretty. when inserting the 'next'
// suggestion we undo until we are at the state at
......@@ -308,7 +317,10 @@ export class SuggestController implements IEditorContribution {
if (modelVersionNow !== model.getAlternativeVersionId()) {
model.undo();
}
this._insertSuggestion(next, false, false, false, keepSuffix);
this._insertSuggestion(
next,
InsertFlags.NoBeforeUndoStop | InsertFlags.NoAfterUndoStop | (flags & InsertFlags.AlternativeOverwriteConfig ? InsertFlags.AlternativeOverwriteConfig : 0)
);
break;
}
});
......@@ -390,7 +402,7 @@ export class SuggestController implements IEditorContribution {
return;
}
this._editor.pushUndoStop();
this._insertSuggestion({ index, item, model: completionModel }, true, false, false, false);
this._insertSuggestion({ index, item, model: completionModel }, InsertFlags.KeepAlternativeSuggestions | InsertFlags.NoBeforeUndoStop | InsertFlags.NoAfterUndoStop);
}, undefined, listener);
});
......@@ -400,9 +412,16 @@ export class SuggestController implements IEditorContribution {
this._editor.focus();
}
acceptSelectedSuggestion(keepAlternativeSuggestions: boolean, keepSuffix: boolean): void {
acceptSelectedSuggestion(keepAlternativeSuggestions: boolean, alternativeOverwriteConfig: boolean): void {
const item = this._widget.getValue().getFocusedItem();
this._insertSuggestion(item, keepAlternativeSuggestions, true, true, keepSuffix);
let flags = 0;
if (keepAlternativeSuggestions) {
flags |= InsertFlags.KeepAlternativeSuggestions;
}
if (alternativeOverwriteConfig) {
flags |= InsertFlags.AlternativeOverwriteConfig;
}
this._insertSuggestion(item, flags);
}
acceptNextSuggestion() {
......@@ -497,44 +516,41 @@ const SuggestCommand = EditorCommand.bindToContribution<SuggestController>(Sugge
registerEditorCommand(new SuggestCommand({
id: 'acceptSelectedSuggestion',
precondition: SuggestContext.Visible,
kbOpts: {
weight: weight,
kbExpr: EditorContextKeys.textInputFocus,
primary: KeyCode.Tab
},
handler(x, args) {
let keepSuffix: boolean;
if (typeof args !== 'object') {
keepSuffix = true;
} else if (typeof args.keepSuffix !== 'boolean') {
keepSuffix = true;
} else {
keepSuffix = args.keepSuffix;
}
x.acceptSelectedSuggestion(true, keepSuffix);
const alternative: boolean = typeof args === 'object' && typeof args.alternative === 'boolean'
? args.alternative
: false;
x.acceptSelectedSuggestion(true, alternative);
}
}));
// normal tab
KeybindingsRegistry.registerKeybindingRule({
id: 'acceptSelectedSuggestion',
when: ContextKeyExpr.and(SuggestContext.Visible, EditorContextKeys.textInputFocus),
primary: KeyCode.Tab,
weight
});
// accept on enter has special rules
KeybindingsRegistry.registerKeybindingRule({
id: 'acceptSelectedSuggestion',
when: ContextKeyExpr.and(SuggestContext.Visible, EditorContextKeys.textInputFocus, SuggestContext.AcceptSuggestionsOnEnter, SuggestContext.MakesTextEdit),
primary: KeyCode.Enter,
weight
});
// shift+enter and shift+tab use the alternative-flag so that the suggest controller
// is doing the opposite of the editor.suggest.overwriteOnAccept-configuration
KeybindingsRegistry.registerKeybindingRule({
id: 'acceptSelectedSuggestion',
when: ContextKeyExpr.and(SuggestContext.Visible, EditorContextKeys.textInputFocus),
primary: KeyMod.Shift | KeyCode.Tab,
secondary: [KeyMod.Shift | KeyCode.Enter],
args: { keepSuffix: false },
args: { alternative: true },
weight
});
registerEditorCommand(new SuggestCommand({
id: 'acceptSelectedSuggestionOnEnter',
precondition: SuggestContext.Visible,
handler: x => x.acceptSelectedSuggestion(false, true),
kbOpts: {
weight: weight,
kbExpr: ContextKeyExpr.and(EditorContextKeys.textInputFocus, SuggestContext.AcceptSuggestionsOnEnter, SuggestContext.MakesTextEdit),
primary: KeyCode.Enter
}
}));
registerEditorCommand(new SuggestCommand({
id: 'hideSuggestWidget',
precondition: SuggestContext.Visible,
......
......@@ -159,6 +159,7 @@ suite('CompletionModel', function () {
leadingLineContent: 's',
characterCountDelta: 0
}, WordDistance.None, {
overwriteOnAccept: false,
snippetsPreventQuickSuggestions: true,
filterGraceful: true,
localityBonus: false,
......@@ -186,6 +187,7 @@ suite('CompletionModel', function () {
leadingLineContent: 's',
characterCountDelta: 0
}, WordDistance.None, {
overwriteOnAccept: false,
snippetsPreventQuickSuggestions: true,
filterGraceful: true,
localityBonus: false,
......@@ -212,6 +214,7 @@ suite('CompletionModel', function () {
leadingLineContent: 's',
characterCountDelta: 0
}, WordDistance.None, {
overwriteOnAccept: false,
snippetsPreventQuickSuggestions: true,
filterGraceful: true,
localityBonus: false,
......
......@@ -675,8 +675,8 @@ suite('SuggestModel - TriggerAndCancelOracle', function () {
return withOracle(async (sugget, editor) => {
class TestCtrl extends SuggestController {
_insertSuggestion(item: ISelectedSuggestion) {
super._insertSuggestion(item, false, true, true, false);
_insertSuggestion(item: ISelectedSuggestion, flags: number = 0) {
super._insertSuggestion(item, flags);
}
}
const ctrl = <TestCtrl>editor.registerAndInstantiateContribution(TestCtrl.ID, TestCtrl);
......
......@@ -3368,6 +3368,10 @@ declare namespace monaco.editor {
* Configuration options for editor suggest widget
*/
export interface ISuggestOptions {
/**
* Overwrite word ends on accept. Default to false.
*/
overwriteOnAccept?: boolean;
/**
* Enable graceful matching. Defaults to true.
*/
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册