UNPKG

fish-lsp

Version:

LSP implementation for fish/fish-shell

141 lines (140 loc) 4.84 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getFlagCommand = getFlagCommand; exports.getFlagDocumentationAsMarkup = getFlagDocumentationAsMarkup; exports.getFlagDocumentationString = getFlagDocumentationString; const node_1 = require("vscode-languageserver-protocol/node"); const exec_1 = require("./exec"); const findFirstFlagIndex = (cmdline) => { for (let i = 0; i < cmdline.length; i++) { const arg = cmdline[i]; if (arg.startsWith('-')) { return i; } } return -1; }; const findFlagStopToken = (inputArray) => { for (let i = 0; i < inputArray.length; i++) { const arg = inputArray[i]; if (arg === '--') { return i; } } return -1; }; const ensureEndOfArgs = (inputArray) => { const stopToken = findFlagStopToken(inputArray); return stopToken === -1 ? inputArray : inputArray.slice(0, stopToken); }; const removeStrings = (input) => { let output = input.replace(/^\s+/, ''); output = output.replace(/^if\s+/, ''); output = output.replace(/^else {2}if\s+/, ''); output = output.replace(/"(.+)"/, ''); output = output.replace(/'(.+)'/, ''); return output; }; const tokenizeInput = (input) => { const removed = removeStrings(input); const tokenized = ensureEndOfArgs(removed.split(/\s/)); return tokenized.filter(t => t.length > 0); }; const generateShellCommandToComplete = (cmdline) => { const firstFlag = findFirstFlagIndex(cmdline); const cmd = cmdline.slice(0, firstFlag); cmd.push('-'); return cmd.join(' '); }; const outputFlags = async (inputArray) => { const toExec = generateShellCommandToComplete(inputArray); const output = await (0, exec_1.execCompleteLine)(toExec); return output.filter((line) => line.startsWith('-')); }; const shortFlag = (flag) => { return flag.startsWith('-') && !flag.startsWith('--'); }; const longFlag = (flag) => { return flag.startsWith('--') && flag.length > 2; }; const hasUnixFlags = (allFlagLines) => { for (const line of allFlagLines) { const [flag, _doc] = line.split('\t') || []; if (!flag) { continue; } if (shortFlag(flag) && flag.length > 2) { return true; } } return false; }; const parseInputFlags = (inputArray, separateShort) => { const result = []; for (let i = 0; i < inputArray.length; i++) { const arg = inputArray[i]; if (arg && shortFlag(arg)) { if (separateShort) { const shortFlags = arg.slice(1).split('').map(ch => '-' + ch); result.push(...shortFlags); } else { result.push(arg); } } else if (arg && longFlag(arg)) { result.push(arg); } } return result; }; const findMatchingFlags = (inputFlags, allFlagLines) => { const output = []; for (const line of allFlagLines) { const [flag, _doc] = line.split('\t'); if (flag && inputFlags.includes(flag)) { output.push(line); } } return output; }; async function getFlagDocumentationStrings(input) { const splitInputArray = tokenizeInput(input); const outputFlagLines = await outputFlags(splitInputArray); const shouldSeparateShortFlags = !hasUnixFlags(outputFlagLines); const parsedInputFlags = parseInputFlags(splitInputArray, shouldSeparateShortFlags); const matchingFlags = findMatchingFlags(parsedInputFlags, outputFlagLines); return matchingFlags .map(line => line.split('\t')) .map(([flag, doc]) => `**\`${flag}\`** *\`${doc}\`*`) .reverse(); } function getFlagCommand(input) { const splitInputArray = tokenizeInput(input); const firstFlag = findFirstFlagIndex(splitInputArray); let cmd = splitInputArray; if (firstFlag !== -1) { cmd = splitInputArray.slice(0, firstFlag); } return cmd.join(' '); } async function getFlagDocumentationAsMarkup(input) { const docString = await getFlagDocumentationString(input); return { kind: node_1.MarkupKind.Markdown, value: docString, }; } async function getFlagDocumentationString(input) { const cmdName = getFlagCommand(input); const flagLines = await getFlagDocumentationStrings(input); const flagString = flagLines.join('\n'); const manpage = await (0, exec_1.execCommandDocs)(cmdName.replaceAll(' ', '-')); const flagDoc = flagString.trim().length > 0 ? ['___', ' ***Flags***', flagString].join('\n') : ''; const manDoc = manpage.trim().length > 0 ? ['___', '```man', manpage, '```'].join('\n') : ''; const afterString = [flagDoc, manDoc].join('\n').trim(); return [ `***\`${cmdName}\`***`, afterString, ].join('\n'); }