mirror of
https://github.com/microsoft/vscode.git
synced 2026-09-25 00:44:05 +01:00
stable tabstop at snippet line start, fixes #11890
This commit is contained in:
@@ -60,43 +60,53 @@ export class CodeSnippet implements ICodeSnippet {
|
||||
}
|
||||
|
||||
public bind(referenceLine: string, deltaLine: number, firstLineDeltaColumn: number, config: IIndentationNormalizer): ICodeSnippet {
|
||||
var resultLines: string[] = [];
|
||||
var resultPlaceHolders: IPlaceHolder[] = [];
|
||||
const resultLines: string[] = [];
|
||||
const resultPlaceHolders: IPlaceHolder[] = [];
|
||||
|
||||
var referenceIndentation = this.extractLineIndentation(referenceLine, firstLineDeltaColumn + 1);
|
||||
var originalLine: string, originalLineIndentation: string, remainingLine: string, indentation: string;
|
||||
var i: number, len: number, j: number, lenJ: number;
|
||||
const referenceIndentation = this.extractLineIndentation(referenceLine, firstLineDeltaColumn + 1);
|
||||
|
||||
// Compute resultLines & keep deltaColumns as a reference for adjusting placeholders
|
||||
var deltaColumns: number[] = [];
|
||||
for (i = 0, len = this.lines.length; i < len; i++) {
|
||||
originalLine = this.lines[i];
|
||||
const deltaColumns: number[] = [];
|
||||
|
||||
for (let i = 0, len = this.lines.length; i < len; i++) {
|
||||
let originalLine = this.lines[i];
|
||||
if (i === 0) {
|
||||
deltaColumns[i + 1] = firstLineDeltaColumn;
|
||||
resultLines[i] = originalLine;
|
||||
} else {
|
||||
originalLineIndentation = this.extractLineIndentation(originalLine);
|
||||
remainingLine = originalLine.substr(originalLineIndentation.length);
|
||||
indentation = config.normalizeIndentation(referenceIndentation + originalLineIndentation);
|
||||
let originalLineIndentation = this.extractLineIndentation(originalLine);
|
||||
let remainingLine = originalLine.substr(originalLineIndentation.length);
|
||||
let indentation = config.normalizeIndentation(referenceIndentation + originalLineIndentation);
|
||||
deltaColumns[i + 1] = indentation.length - originalLineIndentation.length;
|
||||
resultLines[i] = indentation + remainingLine;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute resultPlaceHolders
|
||||
var originalPlaceHolder: IPlaceHolder, originalOccurence: editorCommon.IRange, resultOccurences: editorCommon.IRange[];
|
||||
for (i = 0, len = this.placeHolders.length; i < len; i++) {
|
||||
originalPlaceHolder = this.placeHolders[i];
|
||||
for (const originalPlaceHolder of this.placeHolders) {
|
||||
let resultOccurences = [];
|
||||
|
||||
resultOccurences = [];
|
||||
for (j = 0, lenJ = originalPlaceHolder.occurences.length; j < lenJ; j++) {
|
||||
originalOccurence = originalPlaceHolder.occurences[j];
|
||||
for (let {startLineNumber, startColumn, endLineNumber, endColumn} of originalPlaceHolder.occurences) {
|
||||
|
||||
if (startColumn > 1) {
|
||||
// placeholders that aren't at the beginning of the snippet line
|
||||
// will be moved by how many characters the indentation has been
|
||||
// adjusted
|
||||
startColumn = startColumn + deltaColumns[startLineNumber];
|
||||
endColumn = endColumn + deltaColumns[endLineNumber];
|
||||
|
||||
} else {
|
||||
// placeholders at the beginning of the snippet line
|
||||
// will be indented by the reference indentation
|
||||
startColumn += referenceIndentation.length;
|
||||
endColumn += referenceIndentation.length;
|
||||
}
|
||||
|
||||
resultOccurences.push({
|
||||
startLineNumber: originalOccurence.startLineNumber + deltaLine,
|
||||
startColumn: originalOccurence.startColumn + deltaColumns[originalOccurence.startLineNumber],
|
||||
endLineNumber: originalOccurence.endLineNumber + deltaLine,
|
||||
endColumn: originalOccurence.endColumn + deltaColumns[originalOccurence.endLineNumber]
|
||||
startLineNumber: startLineNumber + deltaLine,
|
||||
startColumn,
|
||||
endLineNumber: endLineNumber + deltaLine,
|
||||
endColumn
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -179,5 +179,63 @@ suite('Editor Contrib - Snippets', () => {
|
||||
assert.equal(snippet.placeHolders.length, 0);
|
||||
assert.deepEqual(snippet.lines, ['', '$scope.$broadcast(\'scroll.infiniteScrollComplete\');', '']);
|
||||
});
|
||||
|
||||
test('bind, adjust indentation', () => {
|
||||
|
||||
// don't move placeholder at the beginning of the line
|
||||
let snippet = CodeSnippet.fromTextmate([
|
||||
'afterEach((done) => {',
|
||||
'\t${1}test${2}',
|
||||
'})'
|
||||
].join('\n'));
|
||||
|
||||
// replace tab-stop with two spaces
|
||||
let boundSnippet = snippet.bind('', 0, 0, {
|
||||
normalizeIndentation(str: string): string {
|
||||
return str.replace(/\t/g, ' ');
|
||||
}
|
||||
});
|
||||
let [first, second] = boundSnippet.placeHolders;
|
||||
assert.equal(first.occurences.length, 1);
|
||||
assert.equal(first.occurences[0].startColumn, 3);
|
||||
assert.equal(second.occurences.length, 1);
|
||||
assert.equal(second.occurences[0].startColumn, 7);
|
||||
|
||||
// keep tab-stop, identity
|
||||
boundSnippet = snippet.bind('', 0, 0, {
|
||||
normalizeIndentation(str: string): string {
|
||||
return str;
|
||||
}
|
||||
});
|
||||
[first, second] = boundSnippet.placeHolders;
|
||||
assert.equal(first.occurences.length, 1);
|
||||
assert.equal(first.occurences[0].startColumn, 2);
|
||||
assert.equal(second.occurences.length, 1);
|
||||
assert.equal(second.occurences[0].startColumn, 6);
|
||||
});
|
||||
|
||||
|
||||
test('issue #11890: Bad cursor position', () => {
|
||||
|
||||
let snippet = CodeSnippet.fromTextmate([
|
||||
'afterEach((done) => {',
|
||||
'${1}\ttest${2}',
|
||||
'})'
|
||||
].join('\n'));
|
||||
|
||||
let boundSnippet = snippet.bind('', 0, 0, {
|
||||
normalizeIndentation(str: string): string {
|
||||
return str.replace(/\t/g, ' ');
|
||||
}
|
||||
});
|
||||
|
||||
assert.equal(boundSnippet.lines[1], ' test');
|
||||
assert.equal(boundSnippet.placeHolders.length, 2);
|
||||
let [first, second] = boundSnippet.placeHolders;
|
||||
assert.equal(first.occurences.length, 1);
|
||||
assert.equal(first.occurences[0].startColumn, 1);
|
||||
assert.equal(second.occurences.length, 1);
|
||||
assert.equal(second.occurences[0].startColumn, 7);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -408,6 +408,30 @@ suite('SnippetController', () => {
|
||||
}, ['af', '\taf']);
|
||||
});
|
||||
|
||||
test('Final tabstop, #11890 stay at the beginning', () => {
|
||||
|
||||
snippetTest((editor, cursor, codeSnippet, controller) => {
|
||||
|
||||
editor.setSelections([
|
||||
new Selection(1, 5, 1, 5)
|
||||
]);
|
||||
|
||||
codeSnippet = CodeSnippet.fromTextmate([
|
||||
'afterEach((done) => {',
|
||||
'${1}\ttest',
|
||||
'});'
|
||||
].join('\n'));
|
||||
|
||||
controller.run(codeSnippet, 2, 0, true);
|
||||
|
||||
assert.equal(editor.getSelections().length, 1);
|
||||
const [first] = editor.getSelections();
|
||||
|
||||
assert.ok(first.equalsRange({ startLineNumber: 2, startColumn: 3, endLineNumber: 2, endColumn: 3 }), first.toString());
|
||||
|
||||
}, [' af']);
|
||||
});
|
||||
|
||||
test('Final tabstop, no tabstop', () => {
|
||||
|
||||
snippetTest((editor, cursor, codeSnippet, controller) => {
|
||||
|
||||
Reference in New Issue
Block a user