fish-lsp
Version:
LSP implementation for fish/fish-shell
151 lines (150 loc) • 5.87 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.execFileAsync = exports.execAsync = void 0;
exports.execEscapedCommand = execEscapedCommand;
exports.execCmd = execCmd;
exports.execAsyncF = execAsyncF;
exports.execAsyncFish = execAsyncFish;
exports.execFishNoExecute = execFishNoExecute;
exports.execCompletions = execCompletions;
exports.execSubCommandCompletions = execSubCommandCompletions;
exports.execCompleteLine = execCompleteLine;
exports.execCompleteSpace = execCompleteSpace;
exports.execCompleteCmdArgs = execCompleteCmdArgs;
exports.execCommandDocs = execCommandDocs;
exports.execCommandType = execCommandType;
exports.documentCommandDescription = documentCommandDescription;
exports.execFindDependency = execFindDependency;
exports.execCommandLocations = execCommandLocations;
const child_process_1 = require("child_process");
const path_1 = require("path");
const util_1 = require("util");
const logger_1 = require("../logger");
const translation_1 = require("./translation");
exports.execAsync = (0, util_1.promisify)(child_process_1.exec);
exports.execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
async function execEscapedCommand(cmd) {
const escapedCommand = cmd.replace(/(["'$`\\])/g, '\\$1');
const { stdout } = await (0, exports.execFileAsync)('fish', ['-P', '--command', escapedCommand]);
if (!stdout)
return [''];
return stdout.trim().split('\n');
}
async function execCmd(cmd) {
const { stdout, stderr } = await (0, exports.execAsync)(cmd, { shell: 'fish' });
if (stderr)
return [''];
return stdout
.toString()
.trim()
.split('\n');
}
async function execAsyncF(cmd) {
const file = (0, path_1.resolve)(__dirname, '../../fish_files/exec.fish');
logger_1.logger.log({ func: 'execAsyncF', file, cmd });
const child = await (0, exports.execFileAsync)(file, [cmd]);
return child.stdout.toString().trim();
}
async function execAsyncFish(cmd) {
return await (0, exports.execAsync)(`fish -c '${cmd}'`);
}
function execFishNoExecute(filepath) {
try {
return (0, child_process_1.execFileSync)('fish', ['--no-execute', filepath], {
encoding: 'utf8',
stdio: ['ignore', 'ignore', 'pipe'],
}).toString();
}
catch (err) {
if (err.stderr) {
return err.stderr.toString();
}
}
}
async function execCompletions(...cmd) {
const file = (0, path_1.resolve)(__dirname, '../../fish_files/get-completion.fish');
const cmpArgs = ['1', `${cmd.join(' ').trim()}`];
const cmps = await (0, exports.execFileAsync)(file, cmpArgs);
return cmps.stdout.trim().split('\n');
}
async function execSubCommandCompletions(...cmd) {
const file = (0, path_1.resolve)(__dirname, '../../fish_files/get-completion.fish');
const cmpArgs = ['2', cmd.join(' ')];
const cmps = await (0, exports.execFileAsync)(file, cmpArgs);
return cmps.stdout.trim().split('\n');
}
async function execCompleteLine(cmd) {
const escapedCmd = cmd.replace(/(["'`\\])/g, '\\$1');
const completeString = `fish -c "complete --do-complete='${escapedCmd}'"`;
const child = await (0, exports.execAsync)(completeString);
if (child.stderr) {
return [''];
}
return child.stdout.trim().split('\n');
}
async function execCompleteSpace(cmd) {
const escapedCommand = cmd.replace(/(["'$`\\])/g, '\\$1');
const completeString = `fish -c "complete --do-complete='${escapedCommand} '"`;
const child = await (0, exports.execAsync)(completeString);
if (child.stderr) {
return [''];
}
return child.stdout.trim().split('\n');
}
async function execCompleteCmdArgs(cmd) {
const exec = (0, path_1.resolve)(__dirname, '../../fish_files/get-command-options.fish');
const args = (0, child_process_1.execFile)(exec, [cmd]);
const results = args.toString().trim().split('\n');
let i = 0;
const fixedResults = [];
while (i < results.length) {
const line = results[i];
if (cmd === 'test') {
fixedResults.push(line);
}
else if (!line.startsWith('-', 0)) {
fixedResults.push(fixedResults.pop() + ' ' + line.trim());
}
else {
fixedResults.push(line);
}
i++;
}
return fixedResults;
}
async function execCommandDocs(cmd) {
const file = (0, path_1.resolve)(__dirname, '../../fish_files/get-documentation.fish');
const docs = await (0, exports.execFileAsync)(file, [cmd]);
const out = docs.stdout;
return out.toString().trim();
}
async function execCommandType(cmd) {
const file = (0, path_1.resolve)(__dirname, '../../fish_files/get-type.fish');
const cmdCheck = cmd.split(' ')[0]?.trim();
const docs = await (0, exports.execFileAsync)(file, [cmdCheck]);
if (docs.stderr) {
return '';
}
return docs.stdout.toString().trim();
}
async function documentCommandDescription(cmd) {
const cmdDescription = await (0, exports.execAsync)(`fish -c "__fish_describe_command ${cmd}" | head -n1`);
return cmdDescription.stdout.trim() || cmd;
}
async function execFindDependency(cmd) {
const file = (0, path_1.resolve)(__dirname, '../../fish_files/get-dependency.fish');
const docs = (0, child_process_1.execFileSync)(file, [cmd]);
return docs.toString().trim();
}
function execCommandLocations(cmd) {
const output = (0, child_process_1.execFileSync)('fish', ['--command', `type -ap ${cmd}`], {
stdio: ['pipe', 'pipe', 'ignore'],
});
return output.toString().trim().split('\n')
.map(line => line.trim())
.filter(line => line.length > 0 && line !== '\n' && line.includes('/'))
.map(line => ({
uri: (0, translation_1.pathToUri)(line),
path: (0, translation_1.uriToPath)(line),
})) || [];
}