mirror of
https://github.com/Microsoft/vscode
synced 2024-09-13 21:55:38 +00:00
Fixes #231: Restore snippet mode if not entering snippet mode
This commit is contained in:
parent
7af75ebf56
commit
fc26dad6cf
|
@ -243,18 +243,28 @@ export class ModelLine {
|
|||
return NO_OP_MARKERS_ADJUSTER;
|
||||
}
|
||||
|
||||
this._markers.sort(ModelLine._compareMarkers);
|
||||
|
||||
var markers = this._markers;
|
||||
var markersLength = markers.length;
|
||||
var markersIndex = 0;
|
||||
var marker = markers[markersIndex];
|
||||
|
||||
// var printMarker = (m:ILineMarker) => {
|
||||
// if (m.stickToPreviousCharacter) {
|
||||
// return '|' + m.column;
|
||||
// }
|
||||
// return m.column + '|';
|
||||
// }
|
||||
// var printMarkers = () => {
|
||||
// return '[' + markers.map( m => m.column).join(', ') + ']';
|
||||
// return '[' + markers.map(printMarker).join(', ') + ']';
|
||||
// };
|
||||
|
||||
let adjust = (toColumn:number, delta:number, minimumAllowedColumn:number, isReplace:boolean, forceMoveMarkers:boolean) => {
|
||||
// console.log('------------- INITIAL MARKERS: ' + printMarkers());
|
||||
|
||||
let adjust = (toColumn:number, delta:number, minimumAllowedColumn:number, forceStickToPrevious:boolean, forceMoveMarkers:boolean) => {
|
||||
// console.log('------------------------------');
|
||||
// console.log('adjust called: toColumn: ' + toColumn + ', delta: ' + delta + ', minimumAllowedColumn: ' + minimumAllowedColumn + ', isReplace: ' + isReplace + ', forceMoveMarkers:' + forceMoveMarkers);
|
||||
// console.log('adjust called: toColumn: ' + toColumn + ', delta: ' + delta + ', minimumAllowedColumn: ' + minimumAllowedColumn + ', forceStickToPrevious: ' + forceStickToPrevious + ', forceMoveMarkers:' + forceMoveMarkers);
|
||||
// console.log('BEFORE::: markersIndex: ' + markersIndex + ' : ' + printMarkers());
|
||||
while (
|
||||
markersIndex < markersLength
|
||||
|
@ -263,7 +273,7 @@ export class ModelLine {
|
|||
|| (
|
||||
!forceMoveMarkers
|
||||
&& marker.column === toColumn
|
||||
&& (isReplace || marker.stickToPreviousCharacter)
|
||||
&& (forceStickToPrevious || marker.stickToPreviousCharacter)
|
||||
)
|
||||
)
|
||||
) {
|
||||
|
@ -287,6 +297,8 @@ export class ModelLine {
|
|||
|
||||
let finish = (delta:number, lineTextLength:number) => {
|
||||
adjust(Number.MAX_VALUE, delta, 1, false, false);
|
||||
|
||||
// console.log('------------- FINAL MARKERS: ' + printMarkers());
|
||||
};
|
||||
|
||||
return {
|
||||
|
@ -296,39 +308,46 @@ export class ModelLine {
|
|||
}
|
||||
|
||||
public applyEdits(changedMarkers: IChangedMarkers, edits:ILineEdit[]): number {
|
||||
// console.log('--> applyEdits: ' + JSON.stringify(edits));
|
||||
var deltaColumn = 0;
|
||||
var resultText = this.text;
|
||||
let deltaColumn = 0;
|
||||
let resultText = this.text;
|
||||
|
||||
var tokensAdjuster = this._createTokensAdjuster();
|
||||
var markersAdjuster = this._createMarkersAdjuster(changedMarkers);
|
||||
let tokensAdjuster = this._createTokensAdjuster();
|
||||
let markersAdjuster = this._createMarkersAdjuster(changedMarkers);
|
||||
|
||||
for (var i = 0, len = edits.length; i < len; i++) {
|
||||
let _oldStartColumn = edits[i].startColumn;
|
||||
let _oldEndColumn = edits[i].endColumn;
|
||||
// console.log('_oldStartColumn: ' + _oldStartColumn + ', _oldEndColumn: ' + _oldEndColumn);
|
||||
let startColumn = deltaColumn + edits[i].startColumn;
|
||||
let endColumn = deltaColumn + edits[i].endColumn;
|
||||
let text = edits[i].text;
|
||||
for (let i = 0, len = edits.length; i < len; i++) {
|
||||
let edit = edits[i];
|
||||
|
||||
// console.log();
|
||||
// console.log('=============================');
|
||||
// console.log('EDIT #' + i + ' [ ' + edit.startColumn + ' -> ' + edit.endColumn + ' ] : <<<' + edit.text + '>>>, forceMoveMarkers: ' + edit.forceMoveMarkers);
|
||||
// console.log('deltaColumn: ' + deltaColumn);
|
||||
|
||||
let startColumn = deltaColumn + edit.startColumn;
|
||||
let endColumn = deltaColumn + edit.endColumn;
|
||||
let deletingCnt = endColumn - startColumn;
|
||||
let insertingCnt = edit.text.length;
|
||||
|
||||
// Adjust tokens & markers before this edit
|
||||
tokensAdjuster.adjust(_oldStartColumn - 1, deltaColumn, 1);
|
||||
markersAdjuster.adjust(_oldStartColumn - 1 + 1, deltaColumn, 1, startColumn !== endColumn, edits[i].forceMoveMarkers);
|
||||
// console.log('Adjust tokens & markers before this edit');
|
||||
tokensAdjuster.adjust(edit.startColumn - 1, deltaColumn, 1);
|
||||
markersAdjuster.adjust(edit.startColumn, deltaColumn, 1, deletingCnt > 0, edit.forceMoveMarkers);
|
||||
|
||||
// Adjust tokens & markers for the common part of this edit
|
||||
let commonLength = Math.min(endColumn - startColumn, text.length);
|
||||
let commonLength = Math.min(deletingCnt, insertingCnt);
|
||||
if (commonLength > 0) {
|
||||
tokensAdjuster.adjust(_oldStartColumn - 1 + commonLength, deltaColumn, startColumn);
|
||||
markersAdjuster.adjust(_oldStartColumn - 1 + 1 + commonLength, deltaColumn, startColumn, true, edits[i].forceMoveMarkers);
|
||||
// console.log('Adjust tokens & markers for the common part of this edit');
|
||||
tokensAdjuster.adjust(edit.startColumn - 1 + commonLength, deltaColumn, startColumn);
|
||||
markersAdjuster.adjust(edit.startColumn + commonLength, deltaColumn, startColumn, deletingCnt > insertingCnt, edit.forceMoveMarkers);
|
||||
}
|
||||
|
||||
// Perform the edit & update `deltaColumn`
|
||||
resultText = resultText.substring(0, startColumn - 1) + text + resultText.substring(endColumn - 1);
|
||||
deltaColumn += text.length - (endColumn - startColumn);
|
||||
resultText = resultText.substring(0, startColumn - 1) + edit.text + resultText.substring(endColumn - 1);
|
||||
deltaColumn += insertingCnt - deletingCnt;
|
||||
|
||||
// Adjust tokens & markers inside this edit
|
||||
tokensAdjuster.adjust(_oldEndColumn, deltaColumn, startColumn);
|
||||
markersAdjuster.adjust(_oldEndColumn + 1, deltaColumn, startColumn, false, edits[i].forceMoveMarkers);
|
||||
// console.log('Adjust tokens & markers inside this edit');
|
||||
tokensAdjuster.adjust(edit.endColumn, deltaColumn, startColumn);
|
||||
markersAdjuster.adjust(edit.endColumn, deltaColumn, startColumn, false, edit.forceMoveMarkers);
|
||||
}
|
||||
|
||||
// Wrap up tokens & markers; adjust remaining if needed
|
||||
|
@ -453,8 +472,6 @@ export class ModelLine {
|
|||
} else {
|
||||
this._markers.push(marker);
|
||||
}
|
||||
|
||||
this._markers.sort(ModelLine._compareMarkers);
|
||||
}
|
||||
|
||||
public addMarkers(markers:ILineMarker[]): void {
|
||||
|
@ -474,8 +491,6 @@ export class ModelLine {
|
|||
} else {
|
||||
this._markers = this._markers.concat(markers);
|
||||
}
|
||||
|
||||
this._markers.sort(ModelLine._compareMarkers);
|
||||
}
|
||||
|
||||
private static _compareMarkers(a:ILineMarker, b:ILineMarker): number {
|
||||
|
|
|
@ -12,9 +12,9 @@ import EventEmitter = require('vs/base/common/eventEmitter');
|
|||
import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions';
|
||||
import {Range} from 'vs/editor/common/core/range';
|
||||
import {Selection} from 'vs/editor/common/core/selection';
|
||||
import {ReplaceCommand} from 'vs/editor/common/commands/replaceCommand';
|
||||
import {IKeybindingService, IKeybindingContextKey} from 'vs/platform/keybinding/common/keybindingService';
|
||||
import {KeyMod, KeyCode} from 'vs/base/common/keyCodes';
|
||||
import {EditOperation} from 'vs/editor/common/core/editOperation';
|
||||
|
||||
interface IParsedLinePlaceHolderInfo {
|
||||
id: string;
|
||||
|
@ -735,7 +735,8 @@ class SnippetController implements ISnippetController {
|
|||
}
|
||||
|
||||
public run(snippet:CodeSnippet, overwriteBefore:number, overwriteAfter:number): void {
|
||||
this.dispose();
|
||||
let prevController = this._currentController;
|
||||
this._currentController = null;
|
||||
|
||||
if (snippet.placeHolders.length === 0) {
|
||||
// No placeholders => execute for all editor selections
|
||||
|
@ -743,6 +744,16 @@ class SnippetController implements ISnippetController {
|
|||
} else {
|
||||
this._runForPrimarySelection(snippet, overwriteBefore, overwriteAfter);
|
||||
}
|
||||
|
||||
if (!this._currentController) {
|
||||
// we didn't end up in snippet mode again => restore previous controller
|
||||
this._currentController = prevController;
|
||||
} else {
|
||||
// we ended up in snippet mode => dispose previous controller if necessary
|
||||
if (prevController) {
|
||||
prevController.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static _getTypeRangeForSelection(model:EditorCommon.IModel, selection:EditorCommon.IEditorSelection, overwriteBefore:number, overwriteAfter:number): EditorCommon.IEditorRange {
|
||||
|
@ -764,16 +775,16 @@ class SnippetController implements ISnippetController {
|
|||
return snippet.bind(model.getLineContent(typeRange.startLineNumber), typeRange.startLineNumber - 1, typeRange.startColumn - 1, editor);
|
||||
}
|
||||
|
||||
private static _getCommandForSnippet(adaptedSnippet:ICodeSnippet, typeRange:EditorCommon.IEditorRange): EditorCommon.ICommand {
|
||||
private static _getCommandForSnippet(adaptedSnippet:ICodeSnippet, typeRange:EditorCommon.IEditorRange): EditorCommon.IIdentifiedSingleEditOperation {
|
||||
var insertText = adaptedSnippet.lines.join('\n');
|
||||
return new ReplaceCommand(typeRange, insertText);
|
||||
return EditOperation.replace(typeRange, insertText);
|
||||
}
|
||||
|
||||
private _runForPrimarySelection(snippet: CodeSnippet, overwriteBefore: number, overwriteAfter: number): void {
|
||||
var initialAlternativeVersionId = this._editor.getModel().getAlternativeVersionId();
|
||||
|
||||
var prepared = SnippetController._prepareSnippet(this._editor, this._editor.getSelection(), snippet, overwriteBefore, overwriteAfter);
|
||||
this._editor.executeCommand('editor.contrib.insertSnippetHelper', SnippetController._getCommandForSnippet(prepared.adaptedSnippet, prepared.typeRange));
|
||||
this._editor.executeEdits('editor.contrib.insertSnippetHelper', [SnippetController._getCommandForSnippet(prepared.adaptedSnippet, prepared.typeRange)]);
|
||||
|
||||
var cursorOnly = SnippetController._getSnippetCursorOnly(prepared.adaptedSnippet);
|
||||
if (cursorOnly) {
|
||||
|
@ -787,16 +798,15 @@ class SnippetController implements ISnippetController {
|
|||
}
|
||||
|
||||
private _runForAllSelections(snippet:CodeSnippet, overwriteBefore:number, overwriteAfter:number): void {
|
||||
var selections = this._editor.getSelections(),
|
||||
i:number,
|
||||
commands:EditorCommon.ICommand[] = [];
|
||||
let selections = this._editor.getSelections(),
|
||||
edits:EditorCommon.IIdentifiedSingleEditOperation[] = [];
|
||||
|
||||
for (i = 0; i < selections.length; i++) {
|
||||
for (let i = 0; i < selections.length; i++) {
|
||||
var prepared = SnippetController._prepareSnippet(this._editor, selections[i], snippet, overwriteBefore, overwriteAfter);
|
||||
commands.push(SnippetController._getCommandForSnippet(prepared.adaptedSnippet, prepared.typeRange));
|
||||
edits.push(SnippetController._getCommandForSnippet(prepared.adaptedSnippet, prepared.typeRange));
|
||||
}
|
||||
|
||||
this._editor.executeCommands('editor.contrib.insertSnippetHelper', commands);
|
||||
this._editor.executeEdits('editor.contrib.insertSnippetHelper', edits);
|
||||
}
|
||||
|
||||
private static _prepareSnippet(editor:EditorCommon.ICommonCodeEditor, selection:EditorCommon.IEditorSelection, snippet:CodeSnippet, overwriteBefore:number, overwriteAfter:number): { typeRange: EditorCommon.IEditorRange; adaptedSnippet: ICodeSnippet; } {
|
||||
|
|
|
@ -77,6 +77,28 @@ suite('Editor Side Editing - collapsed selection', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('replace at selection 2', () => {
|
||||
testCommand(
|
||||
[
|
||||
'first',
|
||||
'second line',
|
||||
'third line',
|
||||
'fourth'
|
||||
],
|
||||
new Selection(1,1,1,6),
|
||||
[
|
||||
EditOperation.replace(new Selection(1,1,1,6), 'something')
|
||||
],
|
||||
[
|
||||
'something',
|
||||
'second line',
|
||||
'third line',
|
||||
'fourth'
|
||||
],
|
||||
new Selection(1,1,1,10)
|
||||
);
|
||||
});
|
||||
|
||||
test('ModelLine.applyEdits uses `isReplace`', () => {
|
||||
testLineEditMarker('something', 1, true, { startColumn: 1, endColumn: 1, text: 'asd', forceMoveMarkers: false }, 1);
|
||||
testLineEditMarker('something', 1, true, { startColumn: 1, endColumn: 1, text: 'asd', forceMoveMarkers: true }, 4);
|
||||
|
|
|
@ -1607,6 +1607,28 @@ suite('Editor Model - ModelLine.applyEdits text & markers', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('delete near markers', () => {
|
||||
testLineEditMarkers(
|
||||
'abcd',
|
||||
[
|
||||
marker(1, 3, true),
|
||||
marker(2, 3, false)
|
||||
],
|
||||
[{
|
||||
startColumn: 3,
|
||||
endColumn: 4,
|
||||
text: '',
|
||||
forceMoveMarkers: false
|
||||
}],
|
||||
'abd',
|
||||
[],
|
||||
[
|
||||
marker(1, 3, true),
|
||||
marker(2, 3, false)
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
test('replace: updates markers 2', () => {
|
||||
testLineEditMarkers(
|
||||
'Hello world, how are you',
|
||||
|
@ -1788,6 +1810,28 @@ suite('Editor Model - ModelLine.applyEdits text & markers', () => {
|
|||
]
|
||||
);
|
||||
});
|
||||
|
||||
test('replace selection', () => {
|
||||
testLineEditMarkers(
|
||||
'first',
|
||||
[
|
||||
marker(1, 1, true),
|
||||
marker(2, 6, false),
|
||||
],
|
||||
[{
|
||||
startColumn: 1,
|
||||
endColumn: 6,
|
||||
text: 'something',
|
||||
forceMoveMarkers: false
|
||||
}],
|
||||
'something',
|
||||
[2],
|
||||
[
|
||||
marker(1, 1, true),
|
||||
marker(2, 10, false),
|
||||
]
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Editor Model - ModelLine.split text & markers', () => {
|
||||
|
|
Loading…
Reference in a new issue