UNPKG

fish-lsp

Version:

LSP implementation for fish/fish-shell

329 lines (328 loc) 11.3 kB
"use strict"; 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.Option = exports.stringIsUnixFlag = exports.stringIsLongFlag = exports.stringIsShortFlag = void 0; exports.findOptionsSet = findOptionsSet; exports.findOptions = findOptions; exports.isMatchingOption = isMatchingOption; exports.findMatchingOptions = findMatchingOptions; exports.isMatchingOptionOrOptionValue = isMatchingOptionOrOptionValue; exports.isMatchingOptionValue = isMatchingOptionValue; const node_types_1 = require("../utils/node-types"); const tree_sitter_1 = require("../utils/tree-sitter"); const LSP = __importStar(require("vscode-languageserver")); const stringIsShortFlag = (str) => str.startsWith('-') && str.length === 2; exports.stringIsShortFlag = stringIsShortFlag; const stringIsLongFlag = (str) => str.startsWith('--'); exports.stringIsLongFlag = stringIsLongFlag; const stringIsUnixFlag = (str) => str.startsWith('-') && str.length > 2 && !str.startsWith('--'); exports.stringIsUnixFlag = stringIsUnixFlag; class Option { shortOptions = []; unixOptions = []; longOptions = []; requiresArgument = false; acceptsMultipleArguments = false; optionalArgument = false; static create(shortOption, longOption) { const option = new Option(); if (shortOption) { option.shortOptions.push(shortOption); } if (longOption) { option.longOptions.push(longOption); } return option; } static long(longOption) { const option = new Option(); option.longOptions.push(longOption); return option; } static short(shortOption) { const option = new Option(); option.shortOptions.push(shortOption); return option; } static unix(unixOption) { const option = new Option(); option.unixOptions.push(unixOption); return option; } static fromRaw(...str) { const option = new Option(); for (const s of str) { if ((0, exports.stringIsLongFlag)(s)) { option.longOptions.push(s); } else if ((0, exports.stringIsShortFlag)(s)) { option.shortOptions.push(s); } else if ((0, exports.stringIsUnixFlag)(s)) { option.unixOptions.push(s); } } return option; } addUnixFlag(...options) { this.unixOptions.push(...options); return this; } withAliases(...optionAlias) { for (const alias of optionAlias) { if ((0, exports.stringIsLongFlag)(alias)) { this.longOptions.push(alias); continue; } if ((0, exports.stringIsShortFlag)(alias)) { this.shortOptions.push(alias); continue; } } return this; } isOption(shortOption, longOption) { if (shortOption) { return this.shortOptions.includes(shortOption); } else if (longOption) { return this.longOptions.includes(longOption); } return false; } withValue() { this.requiresArgument = true; this.optionalArgument = false; this.acceptsMultipleArguments = false; return this; } withOptionalValue() { this.optionalArgument = true; this.requiresArgument = false; this.acceptsMultipleArguments = false; return this; } withMultipleValues() { this.acceptsMultipleArguments = true; this.requiresArgument = true; this.optionalArgument = false; return this; } isSwitch() { return !this.requiresArgument && !this.optionalArgument; } matchesValue(node) { if (this.isSwitch()) { return false; } if ((0, node_types_1.isOption)(node) && node.text.includes('=')) { const [flag] = node.text.split('='); return this.matches({ ...node, text: flag }); } let prev = node.previousSibling; if (this.acceptsMultipleArguments) { while (prev) { if ((0, node_types_1.isOption)(prev) && !prev.text.includes('=')) { return this.matches(prev); } if ((0, node_types_1.isOption)(prev)) return false; prev = prev.previousSibling; } } return !!prev && this.matches(prev); } matches(node, checkWithEquals = true) { if (!(0, node_types_1.isOption)(node)) return false; const nodeText = checkWithEquals && node.text.includes('=') ? node.text.slice(0, node.text.indexOf('=')) : node.text; if ((0, node_types_1.isLongOption)(node)) { return this.matchesLongFlag(nodeText); } if ((0, node_types_1.isShortOption)(node) && this.unixOptions.length >= 1) { return this.matchesUnixFlag(nodeText); } if ((0, node_types_1.isShortOption)(node)) { return this.matchesShortFlag(nodeText); } return false; } matchesLongFlag(text) { if (!text.startsWith('--')) return false; if ((0, exports.stringIsLongFlag)(text)) { return this.longOptions.includes(text); } return false; } matchesUnixFlag(text) { if ((0, exports.stringIsUnixFlag)(text) && text.length > 2) { return this.unixOptions.includes(text); } return false; } matchesShortFlag(text) { if (!text.startsWith('-') || text.startsWith('--')) return false; const chars = text.slice(1).split('').map(char => `-${char}`); return chars.some(char => this.shortOptions.includes(char)); } equals(node, allowEquals = false) { if (!(0, node_types_1.isOption)(node)) false; const text = allowEquals ? node.text.slice(0, node.text.indexOf('=')) : node.text; if ((0, node_types_1.isLongOption)(node)) return this.matchesLongFlag(text); if ((0, node_types_1.isShortOption)(node) && this.unixOptions.length >= 1) return this.matchesUnixFlag(text); if ((0, node_types_1.isShortOption)(node)) return this.matchesShortFlag(text); return false; } equalsRawOption(...rawOption) { for (const option of rawOption) { if ((0, exports.stringIsLongFlag)(option) && this.longOptions.includes(option)) { return true; } if ((0, exports.stringIsShortFlag)(option) && this.shortOptions.includes(option)) { return true; } } return false; } equalsRawShortOption(...rawOption) { return rawOption.some(option => this.shortOptions.includes(option)); } equalsRawLongOption(...rawOption) { return rawOption.some(option => this.longOptions.includes(option)); } equalsOption(other) { const flags = other.getAllFlags(); return this.equalsRawOption(...flags); } findValueRangeAfterEquals(node) { if (!(0, node_types_1.isOption)(node)) return null; if (!node.text.includes('=')) return null; const range = (0, tree_sitter_1.getRange)(node); if (!range) return null; const equalsIndex = node.text.indexOf('='); return LSP.Range.create(range.start.line, range.start.character + equalsIndex + 1, range.end.line, range.end.character); } isSet(node) { if ((0, node_types_1.isOption)(node)) { return this.equals(node) && this.isSwitch(); } return this.matchesValue(node); } getAllFlags() { const result = []; if (this.shortOptions) result.push(...this.shortOptions); if (this.unixOptions) result.push(...this.unixOptions); if (this.longOptions) result.push(...this.longOptions); return result; } toString() { return this.getAllFlags().join(', '); } } exports.Option = Option; function findOptionsSet(nodes, options) { const result = []; for (const node of nodes) { const values = options.filter(o => o.isSet(node)); if (!values) { continue; } values.forEach(option => result.push({ option, value: node })); } return result; } function findOptions(nodes, options) { const remaining = []; const found = []; const unused = Array.from(options); for (const node of nodes) { const values = options.filter(o => o.isSet(node)); if (values.length === 0 && !(0, node_types_1.isOption)(node)) { remaining.push(node); continue; } values.forEach(option => { unused.splice(unused.indexOf(option), 1); found.push({ option, value: node }); }); } return { remaining, found, unused, }; } function isMatchingOption(node, ...option) { if (!(0, node_types_1.isOption)(node)) return false; for (const opt of option) { if (opt.matches(node)) return true; } return false; } function findMatchingOptions(node, ...options) { if (!(0, node_types_1.isOption)(node)) return; return options.find((opt) => opt.matches(node)); } function isMatchingOptionOrOptionValue(node, option) { if (isMatchingOption(node, option)) { return true; } const prevNode = node.previousNamedSibling; if (prevNode?.text.includes('=')) { return false; } if (prevNode && isMatchingOption(prevNode, option) && !(0, node_types_1.isOption)(node)) { return true; } return false; } function isMatchingOptionValue(node, ...options) { if (!node?.isNamed) return false; if ((0, node_types_1.isOption)(node)) { return options.some((option) => option.equals(node, true)); } if (node.previousNamedSibling && (0, node_types_1.isOption)(node.previousNamedSibling)) { return options.some(option => option.matchesValue(node)); } return false; }