fix expansion of snippets with nested tabstops

This commit is contained in:
nightwing 2013-09-05 18:45:51 +04:00
commit 1fa691693e
2 changed files with 92 additions and 22 deletions

View file

@ -282,38 +282,73 @@ var SnippetManager = function() {
if (typeof p != "object")
return;
var id = p.tabstopId;
if (!tabstops[id]) {
tabstops[id] = [];
tabstops[id].index = id;
tabstops[id].value = "";
var ts = tabstops[id];
if (!ts) {
ts = tabstops[id] = [];
ts.index = id;
ts.value = "";
}
if (tabstops[id].indexOf(p) != -1)
if (ts.indexOf(p) !== -1)
return;
tabstops[id].push(p);
ts.push(p);
var i1 = tokens.indexOf(p, i + 1);
if (i1 == -1)
if (i1 === -1)
return;
var value = tokens.slice(i + 1, i1).join("");
if (value)
tabstops[id].value = value;
var value = tokens.slice(i + 1, i1);
var isNested = value.some(function(t) {return typeof t === "object"});
if (isNested && !ts.value) {
ts.value = value;
} else if (value.length && (!ts.value || typeof ts.value !== "string")) {
ts.value = value.join("");
}
});
tabstops.forEach(function(ts) {
ts.value && ts.forEach(function(p) {
var i = tokens.indexOf(p);
var i1 = tokens.indexOf(p, i + 1);
if (i1 == -1)
tokens.splice(i + 1, 0, ts.value, p);
else if (i1 == i + 1)
tokens.splice(i + 1, 0, ts.value);
});
});
// expand tabstop values
tabstops.forEach(function(ts) {ts.length = 0});
var expanding = {};
function copyValue(val) {
var copy = []
for (var i = 0; i < val.length; i++) {
var p = val[i];
if (typeof p == "object") {
if (expanding[p.tabstopId])
continue;
var j = val.lastIndexOf(p, i - 1);
p = copy[j] || {tabstopId: p.tabstopId};
}
copy[i] = p;
}
return copy;
}
for (var i = 0; i < tokens.length; i++) {
var p = tokens[i];
if (typeof p != "object")
continue;
var id = p.tabstopId;
var i1 = tokens.indexOf(p, i + 1);
if (expanding[id] == p) {
expanding[id] = null;
continue;
}
var ts = tabstops[id];
var arg = typeof ts.value == "string" ? [ts.value] : copyValue(ts.value);
arg.unshift(i + 1, Math.max(0, i1 - i));
arg.push(p);
expanding[id] = p;
tokens.splice.apply(tokens, arg);
if (ts.indexOf(p) === -1)
ts.push(p);
};
// convert to plain text
var row = 0, column = 0;
var text = "";
tokens.forEach(function(t) {
if (typeof t == "string") {
if (t[0] == "\n"){
if (typeof t === "string") {
if (t[0] === "\n"){
column = t.length - 1;
row ++;
} else

View file

@ -34,11 +34,20 @@ if (typeof process !== "undefined") {
define(function(require, exports, module) {
"use strict";
var EditSession = require("./edit_session").EditSession;
var Editor = require("./editor").Editor;
var MockRenderer = require("./test/mockrenderer").MockRenderer;
var MultiSelect = require("./multi_select").MultiSelect;
var snippetManager = require("./snippets").snippetManager;
var assert = require("./test/assertions");
module.exports = {
setUp : function(next) {
this.editor = new Editor(new MockRenderer());
next();
},
"test: textmate style format strings" : function() {
var fmt = snippetManager.tmStrFormat;
snippetManager.tmStrFormat("hello", {
@ -86,6 +95,32 @@ module.exports = {
assert.equal(tokens[1].fmt, "\\ul\\/");
assert.equal(tokens[1].guard, "as\\/d");
assert.equal(tokens[1].flag, "g");
},
"test: expand snippet with nested tabstops": function() {
var content = "-${1}-${1:1}--${2:2 ${3} 2}-${3:3 $1 3}-${4:4 $2 4}";
this.editor.setValue("");
snippetManager.insertSnippet(this.editor, content);
assert.equal(this.editor.getValue(), "-1-1--2 3 1 3 2-3 1 3-4 2 3 1 3 2 4");
assert.equal(this.editor.getSelectedText(), "1\n1\n1\n1\n1");
this.editor.tabstopManager.tabNext();
assert.equal(this.editor.getSelectedText(), "2 3 1 3 2\n2 3 1 3 2");
this.editor.tabstopManager.tabNext();
assert.equal(this.editor.getSelectedText(), "3 1 3\n3 1 3\n3 1 3");
this.editor.tabstopManager.tabNext();
assert.equal(this.editor.getSelectedText(), "4 2 3 1 3 2 4");
this.editor.tabstopManager.tabNext();
assert.equal(this.editor.getSelectedText(), "");
this.editor.setValue("");
snippetManager.insertSnippet(this.editor, "-${1:a$2}-${2:b$1}");
assert.equal(this.editor.getValue(), "-ab-ba");
assert.equal(this.editor.getSelectedText(), "ab\na");
this.editor.tabstopManager.tabNext();
assert.equal(this.editor.getSelectedText(), "b\nba");
this.editor.tabstopManager.tabNext();
assert.equal(this.editor.getSelectedText(), "");
}
};