提交 3703614f 编写于 作者: J Johannes Rieken

better support for nested placeholders

上级 9a0567a6
......@@ -89,31 +89,26 @@ class OneSnippet {
this._init();
let prevGroupsIdx = -1;
if (fwd && this._placeholderGroupsIdx < this._placeholderGroups.length - 1) {
prevGroupsIdx = this._placeholderGroupsIdx;
this._placeholderGroupsIdx += 1;
} else if (!fwd && this._placeholderGroupsIdx > 0) {
prevGroupsIdx = this._placeholderGroupsIdx;
this._placeholderGroupsIdx -= 1;
} else {
// the selection of the current placeholder might
// not acurate any more -> simply restore it
}
return this._editor.getModel().changeDecorations(accessor => {
// change stickness to never grow when typing at its edges
// so that in-active tabstops never grow
if (prevGroupsIdx !== -1) {
for (const placeholder of this._placeholderGroups[prevGroupsIdx]) {
const id = this._placeholderDecorations.get(placeholder);
accessor.changeDecorationOptions(id, OneSnippet._decor.inactive);
}
}
const activePlaceholders = new Set<Placeholder>();
// change stickiness to always grow when typing at its edges
// because these decorations represent the currently active
// tabstop. Special case: reaching the final tab stop
// tabstop.
// Special case #1: reaching the final tabstop
// Special case #2: placeholders enclosing active placeholders
const selections: Selection[] = [];
for (const placeholder of this._placeholderGroups[this._placeholderGroupsIdx]) {
const id = this._placeholderDecorations.get(placeholder);
......@@ -121,7 +116,23 @@ class OneSnippet {
selections.push(new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn));
accessor.changeDecorationOptions(id, placeholder.isFinalTabstop ? OneSnippet._decor.activeFinal : OneSnippet._decor.active);
activePlaceholders.add(placeholder);
for (const enclosingPlaceholder of this._snippet.enclosingPlaceholders(placeholder)) {
const id = this._placeholderDecorations.get(enclosingPlaceholder);
accessor.changeDecorationOptions(id, enclosingPlaceholder.isFinalTabstop ? OneSnippet._decor.activeFinal : OneSnippet._decor.active);
activePlaceholders.add(enclosingPlaceholder);
}
}
// change stickness to never grow when typing at its edges
// so that in-active tabstops never grow
this._placeholderDecorations.forEach((id, placeholder) => {
if (!activePlaceholders.has(placeholder)) {
accessor.changeDecorationOptions(id, OneSnippet._decor.inactive);
}
});
return selections;
});
}
......
......@@ -132,6 +132,12 @@ export abstract class Marker {
return result;
}
parent: Marker;
protected _adopt(child: Marker): void {
child.parent = this;
}
toString() {
return '';
}
......@@ -179,6 +185,7 @@ export class Placeholder extends Marker {
constructor(public index: string = '', public defaultValue: Marker[]) {
super();
defaultValue.forEach(this._adopt, this);
}
get isFinalTabstop() {
return this.index === '0';
......@@ -194,6 +201,7 @@ export class Variable extends Marker {
constructor(public name: string = '', public defaultValue: Marker[]) {
super();
defaultValue.forEach(this._adopt, this);
}
get isDefined(): boolean {
return this.resolvedValue !== undefined;
......@@ -271,6 +279,18 @@ export class TextmateSnippet {
return ret;
}
enclosingPlaceholders(placeholder: Placeholder): Placeholder[] {
let ret: Placeholder[] = [];
let { parent } = placeholder;
while (parent) {
if (parent instanceof Placeholder) {
ret.push(parent);
}
parent = parent.parent;
}
return ret;
}
get text() {
return Marker.toString(this.marker);
}
......
......@@ -327,6 +327,33 @@ suite('SnippetParser', () => {
assertLen('${TM_SELECTED_TEXT:def}$0', 0, 3, 0);
});
test('parser, parent node', function () {
let snippet = SnippetParser.parse('This ${1:is ${2:nested}}$0');
assert.equal(snippet.placeholders.length, 3);
let [first, second] = snippet.placeholders;
assert.equal(first.index, '1');
assert.equal(second.index, '2');
assert.ok(second.parent === first);
assert.ok(first.parent === undefined);
snippet = SnippetParser.parse('${VAR:default${1:value}}$0');
assert.equal(snippet.placeholders.length, 2);
[first] = snippet.placeholders;
assert.equal(first.index, '1');
assert.ok(snippet.marker[0] instanceof Variable);
assert.ok(first.parent === snippet.marker[0]);
});
test('TextmateSnippet#enclosingPlaceholders', function () {
let snippet = SnippetParser.parse('This ${1:is ${2:nested}}$0');
let [first, second] = snippet.placeholders;
assert.deepEqual(snippet.enclosingPlaceholders(first), []);
assert.deepEqual(snippet.enclosingPlaceholders(second), [first]);
});
test('TextmateSnippet#offset', () => {
let snippet = SnippetParser.parse('te$1xt');
assert.equal(snippet.offset(snippet.marker[0]), 0);
......
......@@ -378,23 +378,23 @@ suite('SnippetSession', function () {
assertSelections(editor, new Selection(1, 11, 1, 11));
});
// test('snippets, typing with nested placeholder', function () {
test('snippets, typing with nested placeholder', function () {
// editor.setSelection(new Selection(1, 1, 1, 1));
// const session = new SnippetSession(editor, 'This ${1:is ${2:nested}}.$0');
// session.insert();
// assertSelections(editor, new Selection(1, 6, 1, 15));
editor.setSelection(new Selection(1, 1, 1, 1));
const session = new SnippetSession(editor, 'This ${1:is ${2:nested}}.$0');
session.insert();
assertSelections(editor, new Selection(1, 6, 1, 15));
// session.next();
// assertSelections(editor, new Selection(1, 9, 1, 15));
session.next();
assertSelections(editor, new Selection(1, 9, 1, 15));
// editor.trigger('test', 'deleteLeft', {});
// assertSelections(editor, new Selection(1, 9, 1, 9));
editor.trigger('test', 'deleteLeft', {});
assertSelections(editor, new Selection(1, 9, 1, 9));
// editor.trigger('test', 'type', { text: 'XXX' });
// session.prev();
// assertSelections(editor, new Selection(1, 6, 1, 12));
// });
editor.trigger('test', 'type', { text: 'XXX' });
session.prev();
assertSelections(editor, new Selection(1, 6, 1, 12));
});
test('snippets, snippet with variables', function () {
const session = new SnippetSession(editor, '@line=$TM_LINE_NUMBER$0');
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册