UNPKG

fish-lsp

Version:

LSP implementation for fish/fish-shell

99 lines (98 loc) 4.03 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createAliasInlineAction = createAliasInlineAction; exports.createAliasSaveActionNewFile = createAliasSaveActionNewFile; const os_1 = __importDefault(require("os")); const vscode_languageserver_1 = require("vscode-languageserver"); const tree_sitter_1 = require("../utils/tree-sitter"); const exec_1 = require("../utils/exec"); const path_1 = require("path"); const action_kinds_1 = require("./action-kinds"); const translation_1 = require("../utils/translation"); /** * Extracts the function name from an alias node * --- * * ```fish * # handles both cases * alias name='cmd' * alias name 'cmd' * ``` * * --- * @param node The alias node * @returns The function name */ function extractFunctionName(node) { const children = node.children; if (children.length < 2) return ''; const nameNode = children[1]; if (!nameNode) return ''; // Handle both formats: alias name='cmd' and alias name 'cmd' const name = nameNode.text.split('=')[0]?.toString() || ''; return name.trim(); } /** * Creates a quick-fix code action to convert an alias to a function inline * This action will replace the alias line with the function content. */ async function createAliasInlineAction(doc, node) { const aliasCommand = node.text; const funcName = extractFunctionName(node); const stdout = await (0, exec_1.execAsyncF)(`${aliasCommand} && functions ${funcName} | tail +2 | fish_indent`); const edit = vscode_languageserver_1.TextEdit.replace((0, tree_sitter_1.getRange)(node), `\n${stdout}\n`); return { title: `Convert alias '${funcName}' to inline function`, kind: action_kinds_1.SupportedCodeActionKinds.RefactorExtract, edit: { changes: { [doc.uri]: [edit], }, }, isPreferred: true, }; } function createVersionedDocument(uri) { return vscode_languageserver_1.VersionedTextDocumentIdentifier.create(uri, 0); } function createFunctionFileEdit(functionUri, content) { return vscode_languageserver_1.TextDocumentEdit.create(createVersionedDocument(functionUri), [vscode_languageserver_1.TextEdit.insert({ line: 0, character: 0 }, content)]); } function createRemoveAliasEdit(document, node) { return vscode_languageserver_1.TextDocumentEdit.create(createVersionedDocument(document.uri), [vscode_languageserver_1.TextEdit.del((0, tree_sitter_1.getRange)(node))]); } /** * Creates a quick-fix code action to convert an alias to a function file. */ async function createAliasSaveActionNewFile(doc, node) { const aliasCommand = node.text; const funcName = extractFunctionName(node); // Get function content but remove first line (function declaration) and indent const functionContent = await (0, exec_1.execAsyncF)(`${aliasCommand} && functions ${funcName} | tail +2 | fish_indent`); // Create path for new function file const functionPath = (0, path_1.join)(os_1.default.homedir(), '.config', 'fish', 'functions', `${funcName}.fish`); const functionUri = (0, translation_1.pathToUri)(functionPath); // const createFileAction = OptionalVersionedTextDocumentIdentifier.create(functionUri, null) const createFileAction = vscode_languageserver_1.CreateFile.create(functionUri, { ignoreIfExists: false, overwrite: true, }); const workspaceEdit = { documentChanges: [ createFileAction, createFunctionFileEdit(functionUri, functionContent), createRemoveAliasEdit(doc, node), ], }; return { title: `Convert alias '${funcName}' to function in file: ~/.config/fish/functions/${funcName}.fish`, kind: action_kinds_1.SupportedCodeActionKinds.RefactorExtract, edit: workspaceEdit, isPreferred: false, }; }