fish-lsp
Version:
LSP implementation for fish/fish-shell
240 lines (239 loc) • 9.15 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.signatureIndex = void 0;
exports.buildSignature = buildSignature;
exports.getCurrentNodeType = getCurrentNodeType;
exports.lineSignatureBuilder = lineSignatureBuilder;
exports.getPipes = getPipes;
exports.getAliasedCompletionItemSignature = getAliasedCompletionItemSignature;
exports.regexStringSignature = regexStringSignature;
exports.getDefaultSignatures = getDefaultSignatures;
const snippets_1 = require("./utils/snippets");
const NodeTypes = __importStar(require("./utils/node-types"));
const TreeSitter = __importStar(require("./utils/tree-sitter"));
function buildSignature(label, value) {
return {
label: label,
documentation: {
kind: 'markdown',
value: value,
},
};
}
function getCurrentNodeType(input) {
const prebuiltTypes = snippets_1.PrebuiltDocumentationMap.getByName(input);
if (!prebuiltTypes || prebuiltTypes.length === 0) {
return null;
}
let longestDocs = prebuiltTypes[0];
for (const prebuilt of prebuiltTypes) {
if (prebuilt.description.length > longestDocs.description.length) {
longestDocs = prebuilt;
}
}
return longestDocs;
}
function lineSignatureBuilder(lineRootNode, lineCurrentNode, _completeMmap) {
const currentCmd = NodeTypes.findParentCommand(lineCurrentNode) || lineRootNode;
const pipes = getPipes(lineRootNode);
const varNode = getVariableNode(lineRootNode);
const allCmds = getAllCommands(lineRootNode);
const regexOption = getRegexOption(lineRootNode);
if (pipes.length === 1)
return getPipesSignature(pipes);
switch (true) {
case isStringWithRegex(currentCmd.text, regexOption):
return getDefaultSignatures();
case varNode && isSetOrReadWithVarNode(currentCmd?.text || lineRootNode.text, varNode, lineRootNode, allCmds):
return getSignatureForVariable(varNode);
case currentCmd?.text.startsWith('return') || lineRootNode.text.startsWith('return'):
return getReturnStatusSignature();
case allCmds.length === 1:
return getCommandSignature(currentCmd);
default:
return null;
}
}
function getPipes(rootNode) {
const pipeNames = snippets_1.PrebuiltDocumentationMap.getByType('pipe');
return TreeSitter.getChildNodes(rootNode).reduce((acc, node) => {
const pipe = pipeNames.find(p => p.name === node.text);
if (pipe)
acc.push(pipe);
return acc;
}, []);
}
function getVariableNode(rootNode) {
return TreeSitter.getChildNodes(rootNode).find(c => NodeTypes.isVariableDefinition(c));
}
function getAllCommands(rootNode) {
return TreeSitter.getChildNodes(rootNode).filter(c => NodeTypes.isCommand(c));
}
function getRegexOption(rootNode) {
return TreeSitter.getChildNodes(rootNode).find(n => NodeTypes.isMatchingOption(n, { shortOption: '-r', longOption: '--regex' }));
}
function isStringWithRegex(line, regexOption) {
return line.startsWith('string') && !!regexOption;
}
function isSetOrReadWithVarNode(line, varNode, rootNode, allCmds) {
return !!varNode && (line.startsWith('set') || line.startsWith('read')) && allCmds.pop()?.text === rootNode.text.trim();
}
function getSignatureForVariable(varNode) {
const output = getCurrentNodeType(varNode.text);
if (!output)
return null;
return {
signatures: [buildSignature(output.name, output.description)],
activeSignature: 0,
activeParameter: 0,
};
}
function getReturnStatusSignature() {
const output = snippets_1.PrebuiltDocumentationMap.getByType('status').map((o) => `___${o.name}___ - _${o.description}_`).join('\n');
return {
signatures: [buildSignature('$status', output)],
activeSignature: 0,
activeParameter: 0,
};
}
function getPipesSignature(pipes) {
return {
signatures: pipes.map((o) => buildSignature(o.name, `${o.name} - _${o.description}_`)),
activeSignature: 0,
activeParameter: 0,
};
}
function getCommandSignature(firstCmd) {
const output = snippets_1.PrebuiltDocumentationMap.getByType('command').filter(n => n.name === firstCmd.text);
return {
signatures: [buildSignature(firstCmd.text, output.map((o) => `${o.name} - _${o.description}_`).join('\n'))],
activeSignature: 0,
activeParameter: 0,
};
}
function getAliasedCompletionItemSignature(item) {
// const output = PrebuiltDocumentationMap.getByType('command').filter(n => n.name === firstCmd.text);
return {
signatures: [buildSignature(item.label, [
'```fish',
`${item.fishKind} ${item.label} ${item.detail}`,
'```',
].join('\n'))],
activeSignature: 0,
activeParameter: 0,
};
}
function regexStringSignature() {
//const regexItems = stringRegexExpressions;
//let signatureDoc = ["__String Regex Patterns__", "---"];
//for (const item of regexItems) {
// signatureDoc.push(`${item.label} {item.description}`)
//}
const signatureDoc = {
kind: 'markdown',
value: [
markdownStringRepetitions,
markdownStringCharClasses,
markdownStringGroups,
].join('\n---\n'),
};
return {
label: 'Regex Patterns',
documentation: signatureDoc,
};
}
function regexStringCharacterSets() {
return {
label: 'Regex Groups',
documentation: {
kind: 'markdown',
value: markdownStringCharacterSets,
},
};
}
exports.signatureIndex = {
stringRegexPatterns: 0,
stringRegexCharacterSets: 1,
};
function getDefaultSignatures() {
return {
activeParameter: 0,
activeSignature: 0,
signatures: [
regexStringSignature(),
regexStringCharacterSets(),
],
};
}
// REGEX STRING LINES
const markdownStringRepetitions = [
'Repetitions',
'-----------',
'- __*__ refers to 0 or more repetitions of the previous expression',
'- __+__ 1 or more',
'- __?__ 0 or 1.',
'- __{n}__ to exactly n (where n is a number)',
'- __{n,m}__ at least n, no more than m.',
'- __{n,}__ n or more',
].join('\n');
const markdownStringCharClasses = [
'Character Classes',
'-----------------',
'- __.__ any character except newline',
'- __\\d__ a decimal digit and __\\D__, not a decimal digit',
'- __\\s__ whitespace and __\\S__, not whitespace',
'- __\\w__ a “word” character and __\\W__, a “non-word” character',
'- __\\b__ a “word” boundary, and __\\B__, not a word boundary',
'- __[...]__ (where “…” is some characters) is a character set',
'- __[^...]__ is the inverse of the given character set',
'- __[x-y]__ is the range of characters from x-y',
'- __[[:xxx:]]__ is a named character set',
'- __[[:^xxx:]]__ is the inverse of a named character set',
].join('\n');
const markdownStringCharacterSets = [
'__[[:alnum:]]__ : “alphanumeric”',
'__[[:alpha:]]__ : “alphabetic”',
'__[[:ascii:]]__ : “0-127”',
'__[[:blank:]]__ : “space or tab”',
'__[[:cntrl:]]__ : “control character”',
'__[[:digit:]]__ : “decimal digit”',
'__[[:graph:]]__ : “printing, excluding space”',
'__[[:lower:]]__ : “lower case letter”',
'__[[:print:]]__ : “printing, including space”',
'__[[:punct:]]__ : “printing, excluding alphanumeric”',
'__[[:space:]]__ : “white space”',
'__[[:upper:]]__ : “upper case letter”',
'__[[:word:]]__ : “same as w”',
'__[[:xdigit:]]__ : “hexadecimal digit”',
].join('\n');
const markdownStringGroups = [
'Groups',
'------',
'- __(...)__ is a capturing group',
'- __(?:...)__ is a non-capturing group',
'- __\\n__ is a backreference (where n is the number of the group, starting with 1)',
'- __$n__ is a reference from the replacement expression to a group in the match expression.',
].join('\n');