stable tabstop at snippet line start, fixes #11890

This commit is contained in:
Johannes Rieken
2016-10-05 12:34:44 +02:00
parent 95fec447ef
commit 6b515aea32
3 changed files with 113 additions and 21 deletions
+31 -21
View File
@@ -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) => {