fish-lsp
Version:
LSP implementation for fish/fish-shell
122 lines (121 loc) • 4.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.CompletionItemMap = void 0;
exports.splitLine = splitLine;
const types_1 = require("./types");
const exec_1 = require("../exec");
const static_items_1 = require("./static-items");
const startup_config_1 = require("./startup-config");
const markdown_builder_1 = require("../markdown-builder");
class CompletionItemMap {
_items;
constructor(_items = {}) {
this._items = _items;
}
static async initialize() {
const result = {};
const cmdOutputs = new Map();
const topLevelLabels = new Set();
await Promise.all(startup_config_1.SetupItemsFromCommandConfig.map(async (item) => {
const stdout = await (0, exec_1.execCmd)(item.command);
cmdOutputs.set(item.fishKind, stdout);
}));
startup_config_1.SetupItemsFromCommandConfig.forEach((item) => {
const items = [];
const stdout = cmdOutputs.get(item.fishKind);
stdout.forEach((line) => {
if (line.trim().length === 0) {
return;
}
const { label, value } = splitLine(line);
if (item.topLevel) {
if (topLevelLabels.has(label)) {
return;
}
topLevelLabels.add(label);
}
const detail = getCommandsDetail(value || item.detail);
items.push(types_1.FishCompletionItem.create(label, item.fishKind, detail, line));
});
result[item.fishKind] = items;
});
Object.entries(static_items_1.StaticItems).forEach(([key, value]) => {
const kind = key;
if (!result[kind]) {
result[kind] = value.map((item) => types_1.FishCompletionItem.create(item.label, kind, item.detail, item.documentation.toString(), item.examples));
}
if (kind === types_1.FishCompletionItemKind.FUNCTION || kind === types_1.FishCompletionItemKind.VARIABLE) {
const toAdd = value
.filter((item) => !result[kind].find((i) => i.label === item.label))
.map((item) => types_1.FishCompletionItem.create(item.label, kind, item.detail, [
`(${markdown_builder_1.md.italic(kind)}) ${markdown_builder_1.md.bold(item.label)}`,
markdown_builder_1.md.separator(),
item.documentation.toString(),
].join('\n'), item.examples).setUseDocAsDetail());
result[kind].push(...toAdd);
}
});
return new CompletionItemMap(result);
}
get(kind) {
return this._items[kind] || [];
}
get allKinds() {
return Object.keys(this._items);
}
allOfKinds(...kinds) {
return kinds.reduce((acc, kind) => acc.concat(this.get(kind)), []);
}
entries() {
return Object.entries(this._items);
}
forEach(callbackfn) {
this.entries().forEach(([key, value]) => callbackfn(key, value));
}
allCompletionsWithoutCommand() {
return this.allOfKinds(types_1.FishCompletionItemKind.ABBR, types_1.FishCompletionItemKind.ALIAS, types_1.FishCompletionItemKind.BUILTIN, types_1.FishCompletionItemKind.FUNCTION, types_1.FishCompletionItemKind.COMMAND);
}
findLabel(label, ...searchKinds) {
const kinds = searchKinds?.length > 0 ? searchKinds : this.allKinds;
for (const kind of kinds) {
const item = this.get(kind).find((item) => item.label === label);
if (item) {
return item;
}
}
return undefined;
}
get blockedCommands() {
return [
'end',
'else',
'continue',
'break',
];
}
}
exports.CompletionItemMap = CompletionItemMap;
function splitLine(line) {
const index = line.search(/\s/);
if (index === -1) {
return { label: line };
}
const label = line.slice(0, index);
const value = line.slice(index).trimStart();
return { label, value };
}
function getCommandsDetail(value) {
if (value.trim().length === 0) {
return 'command';
}
if (value.startsWith('alias')) {
return 'alias';
}
if (value === 'command link') {
return 'command';
}
if (value === 'command') {
return 'command';
}
return value;
}