UNPKG

fish-lsp

Version:

LSP implementation for fish/fish-shell

313 lines (312 loc) 12.7 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PrebuiltDocumentationMap = exports.fishLspObjs = exports.EnvVariableJson = exports.ExtendedBaseJson = void 0; exports.fromCliOutputToString = fromCliOutputToString; exports.fromCliToMarkdownString = fromCliToMarkdownString; exports.getPrebuiltDocUrlByName = getPrebuiltDocUrlByName; exports.getPrebuiltDocUrl = getPrebuiltDocUrl; const helperCommands_json_1 = __importDefault(require("../snippets/helperCommands.json")); const syntaxHighlightingVariables_json_1 = __importDefault(require("../snippets/syntaxHighlightingVariables.json")); const statusNumbers_json_1 = __importDefault(require("../snippets/statusNumbers.json")); const envVariables_json_1 = __importDefault(require("../snippets/envVariables.json")); const localeVariables_json_1 = __importDefault(require("../snippets/localeVariables.json")); const specialFishVariables_json_1 = __importDefault(require("../snippets/specialFishVariables.json")); const pipesAndRedirects_json_1 = __importDefault(require("../snippets/pipesAndRedirects.json")); const fishlspEnvVariables_json_1 = __importDefault(require("../snippets/fishlspEnvVariables.json")); const markdown_builder_1 = require("./markdown-builder"); var ExtendedBaseJson; (function (ExtendedBaseJson) { function create(o, type, specialType) { return { ...o, type, specialType, }; } ExtendedBaseJson.create = create; function is(o) { return o.type !== undefined && o.exactMatchOptions === undefined; } ExtendedBaseJson.is = is; })(ExtendedBaseJson || (exports.ExtendedBaseJson = ExtendedBaseJson = {})); var EnvVariableJson; (function (EnvVariableJson) { function create(o, exactMatchOptions, options) { return { ...o, type: 'variable', specialType: 'fishlsp', isDeprecated: o.isDeprecated || false, exactMatchOptions, options, }; } EnvVariableJson.create = create; function is(o) { return o.type === 'variable' && o.specialType === 'fishlsp' && o.exactMatchOptions !== undefined; } EnvVariableJson.is = is; const joinValueTypes = (valueType) => { if (!Array.isArray(valueType)) { return String.raw `${valueType}`; } return valueType.map(v => { if (Number.isInteger(v)) { return v; } return "'" + String.raw `${v}` + "'"; }).join(', '); }; const joinDefaultValue = (valueType, defaultValue, optionValue) => { if (!Array.isArray(defaultValue)) { if (valueType === 'string' && defaultValue === '') { return `'${defaultValue}'`; } else if (valueType === 'number') { return `${defaultValue}`; } else if (valueType === 'boolean') { return `'${defaultValue}'`; } else if (valueType === 'array') { return '[\'\']'; } else { return ''; } } else { if (valueType === 'array' && defaultValue.length === 0) { if (Array.isArray(optionValue) && optionValue.some(v => Number.isInteger(v))) { return '[]'; } return '[]'; } else if (valueType === 'array' && defaultValue.length > 0) { return '[' + joinValueTypes(defaultValue) + ']'; } return joinValueTypes(defaultValue); } }; function asCliObject(o) { const options = joinValueTypes(o.options); const defaultValue = joinDefaultValue(o.valueType, o.defaultValue, o.options); return { name: o.name, valueType: o.valueType, description: o.description, exactMatchOptions: o.exactMatchOptions, type: o.type, options, defaultValue, }; } EnvVariableJson.asCliObject = asCliObject; function toCliOutput(o, opts = { includeType: true, includeOptions: true, includeDefaultValue: true, wrap: true, }) { const cli = asCliObject(o); return fromCliOutputToString(cli, opts); } EnvVariableJson.toCliOutput = toCliOutput; function toMarkdownString(o, opts = { includeType: true, includeOptions: true, includeDefaultValue: true, wrap: true, }) { const cli = asCliObject(o); return fromCliToMarkdownString(cli, opts); } EnvVariableJson.toMarkdownString = toMarkdownString; })(EnvVariableJson || (exports.EnvVariableJson = EnvVariableJson = {})); function buildBodySection(subtitle, body, shouldWrap = false, asMarkdown = false) { const hasTitle = () => subtitle.length > 0; const titleStr = !hasTitle() ? '' : `(${subtitle}: `; const trailingBrace = !hasTitle() ? '' : ')'; const separator = asMarkdown ? '\n\n' : '\n'; if (!shouldWrap) return `${titleStr} ${body}${trailingBrace}`; const maxLineLength = 76; const output = []; let currentLine = titleStr; const leftpadBody = !hasTitle() ? '' : ' '.repeat(titleStr.length); const splitBody = body.split(' '); const addComma = (idx) => idx === splitBody.length - 1 ? '' : ','; const words = asMarkdown ? body.split(' ').map((word, idx) => { const newWord = word !== "''" && !Number.isInteger(word) ? word.slice(0, -1) : word; if (Number.isInteger(newWord)) return markdown_builder_1.md.inlineCode(newWord) + addComma(idx); if (newWord.startsWith("'") && newWord.endsWith("'")) { return markdown_builder_1.md.inlineCode(newWord) + addComma(idx); } return markdown_builder_1.md.inlineCode(word); }) : body.split(' '); for (const word of words) { if (currentLine.length + word.length + 1 > maxLineLength) { output.push(currentLine); currentLine = `${leftpadBody}${word} `; } else { currentLine += `${word} `; } } output.push(currentLine); return output.join(separator).trimEnd() + trailingBrace; } function fromCliOutputToString(cli, opts = { includeType: true, includeOptions: true, includeDefaultValue: true, wrap: true, }) { const title = opts?.includeType ? `$${cli.name} <${cli.valueType.toString().toUpperCase()}>` : cli.name; const body = []; body.push(...cli.description.split('\n\n')); if (opts.includeOptions) { if (cli.exactMatchOptions) { body.push(buildBodySection('Options', cli.options, opts.wrap)); } else { body.push(buildBodySection('Example Options', cli.options, opts.wrap)); } } if (opts.includeDefaultValue) body.push(buildBodySection('Default', cli.defaultValue, opts.wrap)); return [ title, ...body.join('\n').trimEnd().split('\n'), ].map(line => `# ${line}`).join('\n'); } function fromCliToMarkdownString(cli, opts = { includeType: true, includeOptions: true, includeDefaultValue: true, wrap: true, }) { const body = []; if (opts.includeOptions) { if (cli.exactMatchOptions) { body.push(buildBodySection(markdown_builder_1.md.bold('Options'), cli.options, opts.wrap, true)); } else { body.push(buildBodySection(markdown_builder_1.md.bold('Example Options'), cli.options, opts.wrap, true)); } } if (opts.includeDefaultValue) body.push(buildBodySection(markdown_builder_1.md.bold('Default'), cli.defaultValue, opts.wrap, true)); return [ `(${markdown_builder_1.md.bold(cli.type)}) ${markdown_builder_1.md.inlineCode(cli.name)} <${cli.valueType.toString().toUpperCase()}>`, cli.description, markdown_builder_1.md.separator(), ...body.join('\n\n').trimEnd().split('\n\n'), ].join('\n\n'); } exports.fishLspObjs = fishlspEnvVariables_json_1.default.map((item) => EnvVariableJson.create(item, item?.exactMatchOptions, item?.options)); class DocumentationMap { map = new Map(); typeMap = new Map(); constructor(data) { data.forEach(item => { const curr = this.map.get(item.name) || []; curr.push(item); this.map.set(item.name, curr); if (!this.typeMap.has(item.type)) this.typeMap.set(item.type, []); this.typeMap.get(item.type).push(item); }); } getByName(name) { return name.startsWith('$') ? this.map.get(name.slice(1))?.filter(item => item.type === 'variable') || [] : this.map.get(name) || []; } getByType(type, specialType) { const allOfType = this.typeMap.get(type) || []; return specialType !== undefined ? allOfType.filter(v => v?.specialType === specialType) : allOfType; } add(item) { const curr = this.map.get(item.name) || []; curr?.push(item); this.map.set(item.name, curr); if (!this.typeMap.has(item.type)) this.typeMap.set(item.type, []); this.typeMap.get(item.type).push(item); } findMatchingNames(query, ...types) { const results = []; this.map.forEach(items => { if (items.filter(item => item.name.startsWith(query) && (types.length === 0 || types.includes(item.type || item.specialType)))) { results.push(...items); } }); return results; } getSpecialVariableAsHoverDoc(name) { const variables = this.getByType('variable'); const searchStr = name.startsWith('$') ? name.slice(1) : name; const needle = searchStr === 'fish_lsp_logfile' ? 'fish_lsp_log_file' : searchStr; const result = variables.find(item => item.name === needle); if (!result) return ''; return [ `(${markdown_builder_1.md.italic('variable')}) - ${markdown_builder_1.md.inlineCode('$' + searchStr)}`, markdown_builder_1.md.separator(), result.description, ].join('\n'); } } const allData = [ ...helperCommands_json_1.default.map((item) => ExtendedBaseJson.create(item, 'command')), ...pipesAndRedirects_json_1.default.map((item) => ExtendedBaseJson.create(item, 'pipe')), ...statusNumbers_json_1.default.map((item) => ExtendedBaseJson.create(item, 'status')), ...syntaxHighlightingVariables_json_1.default.map((item) => ExtendedBaseJson.create(item, 'variable', 'theme')), ...fishlspEnvVariables_json_1.default.map((item) => EnvVariableJson.create(item, item?.exactMatchOptions, item?.options)), ...envVariables_json_1.default.map((item) => ExtendedBaseJson.create(item, 'variable', 'env')), ...localeVariables_json_1.default.map((item) => ExtendedBaseJson.create(item, 'variable', 'locale')), ...specialFishVariables_json_1.default.map((item) => ExtendedBaseJson.create(item, 'variable', 'special')), ]; exports.PrebuiltDocumentationMap = new DocumentationMap(allData); function getPrebuiltDocUrlByName(name) { const objs = exports.PrebuiltDocumentationMap.getByName(name); const res = []; objs.forEach((obj, _index) => { res.push(` - ${getPrebuiltDocUrl(obj)}`); }); return res.join('\n').trim(); } function getPrebuiltDocUrl(obj) { switch (obj.type) { case 'command': return `https://fishshell.com/docs/current/cmds/${obj.name}.html`; case 'pipe': return 'https://fishshell.com/docs/current/language.html#input-output-redirection'; case 'status': return 'https://fishshell.com/docs/current/language.html#variables-status'; case 'variable': default: break; } switch (obj.specialType) { case 'env': return `https://fishshell.com/docs/current/language.html#envvar-${obj.name}`; case 'locale': return `https://fishshell.com/docs/current/language.html#locale-variables-${obj.name}`; case 'theme': return `https://fishshell.com/docs/current/language.html#envvar-${obj.name}`; case 'special': return `https://fishshell.com/docs/current/language.html#envvar-${obj.name}`; default: return ''; } }