fish-lsp
Version:
LSP implementation for fish/fish-shell
182 lines (165 loc) • 4.04 kB
text/typescript
import { spawnSync, SpawnSyncOptionsWithStringEncoding } from 'child_process';
export const BuiltInList = [
'[',
'_',
'abbr',
'and',
'argparse',
'begin',
'bg',
'bind',
'block',
'break',
'breakpoint',
'builtin',
'case',
'cd',
'command',
'commandline',
'complete',
'contains',
'continue',
'count',
'disown',
'echo',
'else',
'emit',
'end',
'eval',
'exec',
'exit',
'false',
'fg',
'for',
'function',
'functions',
'history',
'if',
'jobs',
'math',
'not',
'or',
'path',
'printf',
'pwd',
'random',
'read',
'realpath',
'return',
'set',
'set_color',
'source',
'status',
'string',
'switch',
'test',
'time',
'true',
'type',
'ulimit',
'wait',
'while',
];
// You can generate this list by running `builtin --names` in a fish session
// note that '.', and ':' are removed from the list because they do not contain
// a man-page
const BuiltInSET = new Set(BuiltInList);
// check if string is one of the default fish builtin functions
export function isBuiltin(word: string): boolean {
return BuiltInSET.has(word);
}
const reservedKeywords = [
'[',
'_',
'and',
'argparse',
'begin',
'break',
'builtin',
'case',
'command',
'continue',
'else',
'end',
'eval',
'exec',
'for',
'function',
'if',
'not',
'or',
'read',
'return',
'set',
'status',
'string',
'switch',
'test',
'time',
'and',
'while',
];
const ReservedKeywordSet = new Set(reservedKeywords);
// Reserved keywords are not allowed as function names.
// Found on the `function` manpage.
export function isReservedKeyword(word: string): boolean {
return ReservedKeywordSet.has(word);
}
export function findShell() {
const result = spawnSync('which fish', { shell: true, stdio: ['ignore', 'pipe', 'inherit'], encoding: 'utf-8' });
return result.stdout.toString().trim();
}
const fishShell = findShell();
const spawnOpts: SpawnSyncOptionsWithStringEncoding = {
shell: fishShell,
stdio: ['ignore', 'pipe', 'inherit'],
encoding: 'utf-8',
};
function createFunctionNamesList() {
const result = spawnSync('functions --names | string split -n \'\\n\'', spawnOpts);
return result.stdout.toString().split('\n');
}
export const FunctionNamesList = createFunctionNamesList();
export function isFunction(word: string): boolean {
return FunctionNamesList.includes(word);
}
function createFunctionEventsList() {
const result = spawnSync('functions --handlers | string match -vr \'^Event \\w+\' | string split -n \'\\n\'', spawnOpts);
return result.stdout.toString().split('\n');
}
export const EventNamesList = createFunctionEventsList();
export function isEvent(word: string): boolean {
return EventNamesList.includes(word);
}
function createAbbrList() {
const { stdout } = spawnSync('abbr --show', spawnOpts);
return stdout.toString().split('\n');
}
export const AbbrList = createAbbrList();
function createGlobalVariableList() {
const { stdout } = spawnSync('set -n', spawnOpts);
return stdout.toString().split('\n');
}
export const GlobalVariableList = createGlobalVariableList();
//function createAliasList() {
// // `alias | string unescape | string shorten -m 100`
// const {stdout} = spawnSync(`alias | string unescape --style=var | string split -n '\\n'`, spawnOpts)
// return stdout.toString().split('\n')
//}
//export const AliasList = createAliasList()
// cd /usr/share/fish/completions/
// for i in (rg -e '-a' -l); echo (string split -f 1 '.fish' -m1 $i);end
// commands with potential subcommands
// • string split ...
// • killall node
// • man vim
// • command fish
// useful when checking the current Command for documentation/completion
// suggestions. If a match is hit, check one more node back, and if it is
// not a command, stop searching backwards.
// export function hasPossibleSubCommand(cmd: string) : boolean {
// return SubCommandSet.has(cmd);
// }
// const PossibleSubCommand = [
// ];
// const SubCommandSet = new Set(...PossibleSubCommand);