@microsoft/inshellisense
Advanced tools
Comparing version
@@ -8,2 +8,4 @@ // Copyright (c) Microsoft Corporation. | ||
import log from "../utils/log.js"; | ||
import { loadAliases } from "../runtime/alias.js"; | ||
import { loadLocalSpecsSet } from "../runtime/runtime.js"; | ||
export const supportedShells = shells.join(", "); | ||
@@ -19,2 +21,3 @@ export const action = (program) => async (options) => { | ||
await loadConfig(program); | ||
await loadLocalSpecsSet(); | ||
const shell = options.shell ?? (await inferShell()); | ||
@@ -33,3 +36,4 @@ if (shell == null) { | ||
} | ||
await loadAliases(shell); | ||
await render(shell, options.test ?? false, options.parentTermExit ?? false); | ||
}; |
@@ -35,2 +35,4 @@ // Copyright (c) Microsoft Corporation. | ||
handlePromptEnd() { | ||
if (this.#activeCommand.promptEndMarker != null) | ||
return; | ||
this.#activeCommand.promptEndMarker = this.#terminal.registerMarker(0); | ||
@@ -222,3 +224,5 @@ if (this.#activeCommand.promptEndMarker?.line === this.#terminal.buffer.active.cursorY) { | ||
let command = ""; | ||
let wrappedCommand = ""; | ||
let suggestions = ""; | ||
let isWrapped = false; | ||
for (;;) { | ||
@@ -235,2 +239,3 @@ for (let i = lineY == this.#activeCommand.promptEndMarker.line ? this.#activeCommand.promptText.length : 0; i < this.#terminal.cols; i++) { | ||
command += cleanedChars; | ||
wrappedCommand += cleanedChars; | ||
} | ||
@@ -243,7 +248,12 @@ else { | ||
line = this.#terminal.buffer.active.getLine(lineY); | ||
if (!line?.isWrapped) { | ||
const wrapped = line?.isWrapped || this.#terminal.buffer.active.cursorY + this.#terminal.buffer.active.baseY != lineY - 1; | ||
isWrapped = isWrapped || wrapped; | ||
if (!wrapped) { | ||
break; | ||
} | ||
wrappedCommand = ""; | ||
} | ||
const cursorAtEndOfInput = (this.#activeCommand.promptText.length + command.trim().length) % this.#terminal.cols <= this.#terminal.buffer.active.cursorX; | ||
const cursorAtEndOfInput = isWrapped | ||
? wrappedCommand.trim().length % this.#terminal.cols <= this.#terminal.buffer.active.cursorX | ||
: (this.#activeCommand.promptText.length + command.trimEnd().length) % this.#terminal.cols <= this.#terminal.buffer.active.cursorX; | ||
let hasOutput = false; | ||
@@ -260,3 +270,6 @@ let cell = undefined; | ||
} | ||
const commandPostfix = this.#activeCommand.promptText.length + command.trim().length < this.#terminal.buffer.active.cursorX ? " " : ""; | ||
const postfixActive = isWrapped | ||
? wrappedCommand.trim().length < this.#terminal.buffer.active.cursorX | ||
: this.#activeCommand.promptText.length + command.trimEnd().length < this.#terminal.buffer.active.cursorX; | ||
const commandPostfix = postfixActive ? " " : ""; | ||
this.#activeCommand.persistentOutput = this.#activeCommand.hasOutput && hasOutput; | ||
@@ -263,0 +276,0 @@ this.#activeCommand.hasOutput = hasOutput; |
@@ -11,21 +11,27 @@ // Copyright (c) Microsoft Corporation. | ||
import { buildExecuteShellCommand, resolveCwd } from "./utils.js"; | ||
import { aliasExpand } from "./alias.js"; | ||
import { getConfig } from "../utils/config.js"; | ||
import log from "../utils/log.js"; | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- recursive type, setting as any | ||
const specSet = {}; | ||
speclist.forEach((s) => { | ||
let activeSet = specSet; | ||
const specRoutes = s.split("/"); | ||
specRoutes.forEach((route, idx) => { | ||
if (typeof activeSet !== "object") { | ||
return; | ||
} | ||
if (idx === specRoutes.length - 1) { | ||
const prefix = versionedSpeclist.includes(s) ? "/index.js" : `.js`; | ||
activeSet[route] = `@withfig/autocomplete/build/${s}${prefix}`; | ||
} | ||
else { | ||
activeSet[route] = activeSet[route] || {}; | ||
activeSet = activeSet[route]; | ||
} | ||
function loadSpecsSet(speclist, versionedSpeclist, specsPath) { | ||
speclist.forEach((s) => { | ||
let activeSet = specSet; | ||
const specRoutes = s.split("/"); | ||
specRoutes.forEach((route, idx) => { | ||
if (typeof activeSet !== "object") { | ||
return; | ||
} | ||
if (idx === specRoutes.length - 1) { | ||
const prefix = versionedSpeclist.includes(s) ? "/index.js" : `.js`; | ||
activeSet[route] = `${specsPath}/${s}${prefix}`; | ||
} | ||
else { | ||
activeSet[route] = activeSet[route] || {}; | ||
activeSet = activeSet[route]; | ||
} | ||
}); | ||
}); | ||
}); | ||
} | ||
loadSpecsSet(speclist, versionedSpeclist, `@withfig/autocomplete/build`); | ||
const loadedSpecs = {}; | ||
@@ -54,4 +60,23 @@ const loadSpec = async (cmd) => { | ||
}; | ||
export const loadLocalSpecsSet = async () => { | ||
const specsPath = getConfig()?.specs?.path; | ||
if (!specsPath) { | ||
return; | ||
} | ||
try { | ||
await Promise.allSettled(specsPath.map((specPath) => import(path.join(specPath, "index.js")) | ||
.then((res) => { | ||
const { default: speclist, diffVersionedCompletions: versionedSpeclist } = res; | ||
loadSpecsSet(speclist, versionedSpeclist, specPath); | ||
}) | ||
.catch((e) => { | ||
log.debug({ msg: "load local spec failed", e: e.message, specPath }); | ||
}))); | ||
} | ||
catch (e) { | ||
log.debug({ msg: "load local specs failed", e: e.message, specsPath }); | ||
} | ||
}; | ||
export const getSuggestions = async (cmd, cwd, shell) => { | ||
const activeCmd = parseCommand(cmd); | ||
let activeCmd = parseCommand(cmd); | ||
const rootToken = activeCmd.at(0); | ||
@@ -61,2 +86,3 @@ if (activeCmd.length === 0 || !rootToken?.complete) { | ||
} | ||
activeCmd = aliasExpand(activeCmd); | ||
const spec = await loadSpec(activeCmd); | ||
@@ -133,3 +159,7 @@ if (spec == null) | ||
else { | ||
parentCommand.subcommands[subcommandIdx] = { ...subcommand, ...partSpec, loadSpec: undefined }; | ||
parentCommand.subcommands[subcommandIdx] = { | ||
...subcommand, | ||
...partSpec, | ||
loadSpec: undefined, | ||
}; | ||
return parentCommand.subcommands[subcommandIdx]; | ||
@@ -140,7 +170,15 @@ } | ||
const spec = await lazyLoadSpec(subcommand.loadSpec); | ||
parentCommand.subcommands[subcommandIdx] = { ...subcommand, ...(getSubcommand(spec) ?? []), loadSpec: undefined }; | ||
parentCommand.subcommands[subcommandIdx] = { | ||
...subcommand, | ||
...(getSubcommand(spec) ?? []), | ||
loadSpec: undefined, | ||
}; | ||
return parentCommand.subcommands[subcommandIdx]; | ||
} | ||
case "object": { | ||
parentCommand.subcommands[subcommandIdx] = { ...subcommand, ...(subcommand.loadSpec ?? {}), loadSpec: undefined }; | ||
parentCommand.subcommands[subcommandIdx] = { | ||
...subcommand, | ||
...(subcommand.loadSpec ?? {}), | ||
loadSpec: undefined, | ||
}; | ||
return parentCommand.subcommands[subcommandIdx]; | ||
@@ -172,3 +210,6 @@ } | ||
} | ||
return runSubcommand(tokens.slice(1), subcommand, cwd, persistentOptions, acceptedTokens.concat({ ...activeToken, isPersistent })); | ||
return runSubcommand(tokens.slice(1), subcommand, cwd, persistentOptions, acceptedTokens.concat({ | ||
...activeToken, | ||
isPersistent, | ||
})); | ||
}; | ||
@@ -175,0 +216,0 @@ const runArg = async (tokens, args, subcommand, cwd, persistentOptions, acceptedTokens, fromOption, fromVariadic) => { |
@@ -33,2 +33,7 @@ // Copyright (c) Microsoft Corporation. | ||
}; | ||
const specPathsSchema = { | ||
type: "array", | ||
items: { type: "string" }, | ||
nullable: true, | ||
}; | ||
const configSchema = { | ||
@@ -59,2 +64,9 @@ type: "object", | ||
}, | ||
specs: { | ||
type: "object", | ||
nullable: true, | ||
properties: { | ||
path: specPathsSchema, | ||
}, | ||
}, | ||
}, | ||
@@ -103,2 +115,5 @@ additionalProperties: false, | ||
}, | ||
specs: { | ||
path: [`${os.homedir()}/.fig/autocomplete/build`, ...(config?.specs?.path ?? [])], | ||
}, | ||
}; | ||
@@ -105,0 +120,0 @@ } |
{ | ||
"name": "@microsoft/inshellisense", | ||
"version": "0.0.1-rc.11", | ||
"version": "0.0.1-rc.12", | ||
"description": "IDE style command line auto complete", | ||
@@ -5,0 +5,0 @@ "type": "module", |
124100
4.02%40
2.56%2112
6.72%