@unisnips/ultisnips
Version:
Utilities for converting ultisnips in unisnips project
277 lines • 10.7 kB
JavaScript
;
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spread = (this && this.__spread) || function () {
for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
return ar;
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var fs = __importStar(require("fs"));
var path = __importStar(require("path"));
var lodash_omit_1 = __importDefault(require("lodash.omit"));
var tokenizer_1 = require("./tokenizer");
var ultisnips_1 = require("./ultisnips");
var position_1 = require("../util/position");
var ReadState;
(function (ReadState) {
ReadState[ReadState["BLANK"] = 0] = "BLANK";
ReadState[ReadState["SNIPPET_CONTENT"] = 1] = "SNIPPET_CONTENT";
})(ReadState || (ReadState = {}));
var PRIORITY_PATTERN = /^priority (-?\d+)$/;
var EXTENDS_PATTERN = /^extends (.+)?$/;
var SNIPPET_HEAD_PATTERN = /^snippet\s+(.*)\s+"(.*)"(\s+(\w+)\s*)?$/;
var END_SNIPPET_PATTERN = /^endsnippet\s*$/;
function parseSnippets(snippetCode, opts) {
var snippetsFilePath = opts.snippetsFilePath, verbose = opts.verbose;
var list = [];
var currentSnippet;
var state = ReadState.BLANK;
var currentPriority = 0;
snippetCode.split(/\n/).forEach(function (line, index) {
if (state == ReadState.BLANK) {
if (/^\s*$/.test(line)) {
return; //=> blank line, nothing to do
}
if (/^\s*#.*$/.test(line)) {
return; //=> comment line, nothing to do.
}
var priorityMatch = PRIORITY_PATTERN.exec(line);
if (priorityMatch) {
currentPriority = parseInt(priorityMatch[1]);
return; // priority for snippets.
}
var extendsMatch = EXTENDS_PATTERN.exec(line);
if (extendsMatch) {
var typeExtended = extendsMatch[1];
if (opts.onExtends) {
var extendedTypes = [typeExtended];
try {
var extraSnippets = opts.onExtends({
extendedTypes: extendedTypes,
snippetsFilePath: opts.snippetsFilePath,
}, {
parseForDefinitions: function (innerContent, innerOpts) {
if (innerOpts === void 0) { innerOpts = {}; }
return parseSnippets(innerContent, innerOpts);
},
});
list.push.apply(list, __spread(extraSnippets));
}
catch (error) {
console.error("Error in onExtends " + extendedTypes);
if (verbose) {
console.error(error);
}
}
}
else {
if (snippetsFilePath) {
var typeExtendedSnippetFile = path.join(path.dirname(snippetsFilePath), typeExtended) + '.snippets';
try {
var content = fs.readFileSync(typeExtendedSnippetFile, 'utf-8');
var extraSnippets = parseSnippets(content, __assign(__assign({}, opts), { snippetsFilePath: typeExtendedSnippetFile }));
list.push.apply(list, __spread(extraSnippets));
}
catch (e) {
console.error("Unable to parse: " + typeExtendedSnippetFile + " required via " + snippetsFilePath + ":" + (index +
1) + " : " + line, verbose ? e : '');
}
}
}
return; // extended types
}
var m = SNIPPET_HEAD_PATTERN.exec(line);
if (m) {
var start = {
line: index,
column: 0,
};
currentSnippet = {
trigger: m[1],
description: m[2],
code: [],
body: '',
placeholders: [],
priority: currentPriority,
flags: m[4],
position: {
start: start,
end: __assign({}, start),
},
};
list.push(currentSnippet);
state = ReadState.SNIPPET_CONTENT;
return; //=> done
}
else {
// console.error('Error at line: ' + (index + 1) + ', unable to parse: ' + line)
}
}
if (state == ReadState.SNIPPET_CONTENT) {
if (END_SNIPPET_PATTERN.test(line)) {
Object.assign(currentSnippet.position.end, {
line: index,
column: 0,
});
currentSnippet.body = currentSnippet.code.join('\n');
state = ReadState.BLANK;
return; // => done reading snippets
}
currentSnippet.code.push(line);
}
});
return list;
}
/**
* Calculate 'bodyPosition' of a marker
*/
function calcMarkerPositionInSnippet(def, marker) {
var defStartPosition = position_1.TextPosition.fromUnistPoint(def.position.start);
var colOffset = marker.start.column;
var lineOffset = marker.start.line - defStartPosition.line - 1;
var start = defStartPosition.clone();
start.column += colOffset;
start.line = lineOffset;
start.offset = marker.start.offset;
var end = new position_1.TextPosition(marker.end.line - defStartPosition.line - 1, start.column + (marker.end.column - marker.start.column));
if (marker.token) {
end.offset = marker.token.end.offset;
}
// console.table({ start, end })
return {
start: start,
end: end,
};
}
/**
* Detect the placeholders names from a UltiSnips template. The placeholders
* are surrounded by brackets for easier replacement.
*/
function detectPlaceholders(def) {
var result = [];
var markerIdMap = new Map();
var pairs = ultisnips_1.parseUltiSnips(def).pairs;
pairs.forEach(function (pair, i) {
var token = pair.token, parent = pair.parent, marker = pair.marker;
// console.log('token', token)
var placeholder;
var partialData;
if (token instanceof tokenizer_1.VisualToken) {
partialData = {
valueType: 'variable',
variable: {
type: 'builtin',
name: 'UNI_SELECTED_TEXT',
},
};
}
else if (token instanceof tokenizer_1.MirrorToken || token instanceof tokenizer_1.TabStopToken) {
partialData = {
valueType: 'tabstop',
index: token.number,
description: token.initialText,
};
if ('transform' in marker) {
if (marker.transform) {
partialData.transform = marker.transform.getTokenNodeData();
partialData.description = '';
}
}
}
else if (token instanceof tokenizer_1.ScriptCodeToken) {
partialData = {
valueType: 'script',
scriptInfo: {
scriptType: token.scriptType,
code: token.scriptCode,
},
};
}
else if (token instanceof tokenizer_1.UniSnipsVariableToken) {
partialData = {
valueType: 'variable',
variable: {
type: 'builtin',
name: token.name,
},
};
}
// else if (token instanceof TransformationToken) {
// console.log('trans token', token)
// }
if (partialData) {
var markerNode = marker.toTokenNode();
// console.log('marker', marker.markerType)
var p = calcMarkerPositionInSnippet(def, marker);
var bodyPosition = {
start: p.start.toUnistPosition(),
end: p.end.toUnistPosition(),
};
placeholder = __assign(__assign({}, partialData), { id: i, bodyPosition: bodyPosition, extra: {
marker: markerNode,
} });
markerIdMap.set(marker, placeholder.id);
if (marker.parent) {
var parentId = markerIdMap.get(marker.parent);
if (parentId) {
placeholder.parentId = parentId;
}
}
result.push(placeholder);
}
});
return result;
}
function parse(input, opts) {
if (opts === void 0) { opts = {}; }
var originSnippets = parseSnippets(input, opts);
var snippets = [];
originSnippets.forEach(function (ultiSnippet) {
var snippet = lodash_omit_1.default(ultiSnippet, ['code']);
var placeholders = detectPlaceholders(ultiSnippet);
placeholders.forEach(function (placeholder) {
snippet.placeholders.push(placeholder);
});
snippets.push(snippet);
});
return {
definitions: snippets,
};
}
exports.parse = parse;
//# sourceMappingURL=index.js.map