Skip to content

Commit

Permalink
allow final tabstop snippets for all cursors, #9764
Browse files Browse the repository at this point in the history
  • Loading branch information
jrieken committed Aug 23, 2016
1 parent a6d74ab commit 5fbe501
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 11 deletions.
44 changes: 36 additions & 8 deletions src/vs/editor/contrib/snippet/common/snippetController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -479,19 +479,47 @@ export class SnippetController {
}

private _runForAllSelections(snippet: CodeSnippet, overwriteBefore: number, overwriteAfter: number, stripPrefix?: boolean): void {
let selections = this._editor.getSelections(),
edits: editorCommon.IIdentifiedSingleEditOperation[] = [];

const edits: editorCommon.IIdentifiedSingleEditOperation[] = [];
const selections = this._editor.getSelections();
let lineDelta = 0;
let columnDelta = 0;

for (let i = 0; i < selections.length; i++) {
let prepared = SnippetController._prepareSnippet(this._editor, selections[i], snippet, overwriteBefore, overwriteAfter, stripPrefix);
SnippetController._addCommandForSnippet(this._editor.getModel(), prepared.adaptedSnippet, prepared.typeRange, edits);
let {adaptedSnippet, typeRange} = SnippetController._prepareSnippet(this._editor, selections[i], snippet, overwriteBefore, overwriteAfter, stripPrefix);
SnippetController._addCommandForSnippet(this._editor.getModel(), adaptedSnippet, typeRange, edits);

if (i === 0 && snippet.isSingleTabstopOnly) {
const finalCursorPos = SnippetController._getSnippetCursorOnly(adaptedSnippet);
const editEnd = typeRange.getEndPosition();
editEnd.lineNumber += adaptedSnippet.lines.length - 1;
editEnd.column = adaptedSnippet.lines[adaptedSnippet.lines.length - 1].length + 1;

lineDelta = finalCursorPos.lineNumber - editEnd.lineNumber;
columnDelta = finalCursorPos.column - editEnd.column;
}
}

if (edits.length > 0) {
this._editor.pushUndoStop();
this._editor.executeEdits('editor.contrib.insertSnippetHelper', edits);
this._editor.pushUndoStop();
if (edits.length === 0) {
return;
}

const cursorStateComputer: editorCommon.ICursorStateComputer = function (inverseEdits) {

return inverseEdits.map((edit, i) => {

let {endLineNumber, endColumn} = edit.range;
endLineNumber += lineDelta;
endColumn += columnDelta;

return new Selection(endLineNumber, endColumn, endLineNumber, endColumn);
});
};

const model = this._editor.getModel();
model.pushStackElement();
this._editor.setSelections(model.pushEditOperations(selections, edits, cursorStateComputer));
model.pushStackElement();
}

private static _prepareSnippet(editor: editorCommon.ICommonCodeEditor, selection: Selection, snippet: CodeSnippet, overwriteBefore: number, overwriteAfter: number, stripPrefix = true): { typeRange: Range; adaptedSnippet: ICodeSnippet; } {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ suite('SnippetController', () => {
});
});

test('Final tabstop with multiple selection', () => {
test('Final tabstop with multiple selections', () => {
snippetTest((editor, cursor, codeSnippet, snippetController) => {
editor.setSelections([
new Selection(1, 1, 1, 1),
Expand All @@ -233,8 +233,53 @@ suite('SnippetController', () => {

assert.equal(editor.getSelections().length, 2);
const [first, second] = editor.getSelections();
assert.ok(first.equalsRange({ startLineNumber: 1, startColumn: 4, endLineNumber: 1, endColumn: 4 }));
assert.ok(second.equalsRange({ startLineNumber: 2, startColumn: 4, endLineNumber: 2, endColumn: 4 }));
assert.ok(first.equalsRange({ startLineNumber: 1, startColumn: 4, endLineNumber: 1, endColumn: 4 }), first.toString());
assert.ok(second.equalsRange({ startLineNumber: 2, startColumn: 4, endLineNumber: 2, endColumn: 4 }), second.toString());
});

snippetTest((editor, cursor, codeSnippet, snippetController) => {
editor.setSelections([
new Selection(1, 1, 1, 1),
new Selection(2, 1, 2, 1),
]);

codeSnippet = new CodeSnippet('foo{{}}bar');
snippetController.run(codeSnippet, 0, 0, false);

assert.equal(editor.getSelections().length, 2);
const [first, second] = editor.getSelections();
assert.ok(first.equalsRange({ startLineNumber: 1, startColumn: 4, endLineNumber: 1, endColumn: 4 }), first.toString());
assert.ok(second.equalsRange({ startLineNumber: 2, startColumn: 4, endLineNumber: 2, endColumn: 4 }), second.toString());
});

snippetTest((editor, cursor, codeSnippet, snippetController) => {
editor.setSelections([
new Selection(1, 1, 1, 1),
new Selection(1, 5, 1, 5),
]);

codeSnippet = new CodeSnippet('foo{{}}bar');
snippetController.run(codeSnippet, 0, 0, false);

assert.equal(editor.getSelections().length, 2);
const [first, second] = editor.getSelections();
assert.ok(first.equalsRange({ startLineNumber: 1, startColumn: 4, endLineNumber: 1, endColumn: 4 }), first.toString());
assert.ok(second.equalsRange({ startLineNumber: 1, startColumn: 14, endLineNumber: 1, endColumn: 14 }), second.toString());
});

snippetTest((editor, cursor, codeSnippet, snippetController) => {
editor.setSelections([
new Selection(1, 1, 1, 1),
new Selection(1, 5, 1, 5),
]);

codeSnippet = new CodeSnippet('foo\n{{}}\nbar');
snippetController.run(codeSnippet, 0, 0, false);

assert.equal(editor.getSelections().length, 2);
const [first, second] = editor.getSelections();
assert.ok(first.equalsRange({ startLineNumber: 2, startColumn: 1, endLineNumber: 2, endColumn: 1 }), first.toString());
assert.ok(second.equalsRange({ startLineNumber: 4, startColumn: 1, endLineNumber: 4, endColumn: 1 }), second.toString());
});
});
});

0 comments on commit 5fbe501

Please sign in to comment.