From a8496790927c5ec0401993fc252d6877785450ec Mon Sep 17 00:00:00 2001 From: Chapman Pendery Date: Fri, 12 Apr 2024 13:58:08 -0700 Subject: [PATCH 1/2] refactor: add offical shellenv command for plugging inshellisense into shell config startups Signed-off-by: Chapman Pendery --- README.md | 9 +++++++++ src/commands/root.ts | 3 +-- src/commands/shellenv.ts | 23 +++++++++++++++++++++++ src/index.ts | 3 ++- src/runtime/utils.ts | 2 +- src/ui/ui-root.ts | 5 +---- src/utils/shell.ts | 12 ++++++++++++ 7 files changed, 49 insertions(+), 8 deletions(-) create mode 100644 src/commands/shellenv.ts diff --git a/README.md b/README.md index 2534f8e..e20aba0 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,15 @@ npm install -g @microsoft/inshellisense After completing the installation, you can run `is` to start the autocomplete session for your desired shell. Additionally, inshellisense is also aliased under `inshellisense` after installation. +### Shell Plugin + +If you'd like to automatically start inshellisense when you open your shell, run the respective command for your shell. After running the command, inshellisense will automatically open when you start any new shell session: + +```shell +# bash +is shellenv bash >> ~/.bashrc +``` + ### Usage | Action | Command | Description | diff --git a/src/commands/root.ts b/src/commands/root.ts index e534ba7..f7bb1c1 100644 --- a/src/commands/root.ts +++ b/src/commands/root.ts @@ -17,7 +17,6 @@ type RootCommandOptions = { verbose: boolean | undefined; check: boolean | undefined; test: boolean | undefined; - parentTermExit: boolean | undefined; }; export const action = (program: Command) => async (options: RootCommandOptions) => { @@ -46,5 +45,5 @@ export const action = (program: Command) => async (options: RootCommandOptions) await setupBashPreExec(); } await loadAliases(shell); - await render(shell, options.test ?? false, options.parentTermExit ?? false); + await render(shell, options.test ?? false); }; diff --git a/src/commands/shellenv.ts b/src/commands/shellenv.ts new file mode 100644 index 0000000..70f8d1b --- /dev/null +++ b/src/commands/shellenv.ts @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { Command } from "commander"; +import { Shell, shellEnvSupportedShells as shells, getShellConfig } from "../utils/shell.js"; + +const supportedShells = shells.join(", "); + +const action = (program: Command) => async (shell: string) => { + if (!shells.map((s) => s.valueOf()).includes(shell)) { + program.error(`Unsupported shell: '${shell}', supported shells: ${supportedShells}`, { exitCode: 1 }); + } + const config = getShellConfig(shell as Shell); + process.stdout.write(`\n\n# ---------------- inshellisense shell plugin ----------------\n${config}`); + process.exit(0); +}; + +const cmd = new Command("shellenv"); +cmd.description(`generates shell configurations for the provided shell`); +cmd.argument("", `shell to generate configuration for, supported shells: ${supportedShells}`); +cmd.action(action(cmd)); + +export default cmd; diff --git a/src/index.ts b/src/index.ts index b10e866..b03f981 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,6 +9,7 @@ import { Command, Option } from "commander"; import complete from "./commands/complete.js"; import uninstall from "./commands/uninstall.js"; +import shellenv from "./commands/shellenv.js"; import { action, supportedShells } from "./commands/root.js"; import { getVersion } from "./utils/version.js"; @@ -27,12 +28,12 @@ program .action(action(program)) .option("-s, --shell ", `shell to use for command execution, supported shells: ${supportedShells}`) .option("-c, --check", `check if shell is in an inshellisense session`) - .option("--parent-term-exit", `when inshellisense is closed, kill the parent process`) .addOption(hiddenOption("-T, --test", "used to make e2e tests reproducible across machines")) .option("-V, --verbose", `enable verbose logging`) .showHelpAfterError("(add --help for additional information)"); program.addCommand(complete); program.addCommand(uninstall); +program.addCommand(shellenv); program.parse(); diff --git a/src/runtime/utils.ts b/src/runtime/utils.ts index eee7642..c9c1d4e 100644 --- a/src/runtime/utils.ts +++ b/src/runtime/utils.ts @@ -16,7 +16,7 @@ export type ExecuteShellCommandTTYResult = { export const buildExecuteShellCommand = (timeout: number): Fig.ExecuteCommandFunction => async ({ command, env, args, cwd }: Fig.ExecuteCommandInput): Promise => { - const child = spawn(command, args, { cwd, env }); + const child = spawn(command, args, { cwd, env: { ...env, ISTERM: "1" } }); setTimeout(() => child.kill("SIGKILL"), timeout); let stdout = ""; let stderr = ""; diff --git a/src/ui/ui-root.ts b/src/ui/ui-root.ts index 8761975..a6f978c 100644 --- a/src/ui/ui-root.ts +++ b/src/ui/ui-root.ts @@ -16,7 +16,7 @@ export const renderConfirmation = (live: boolean): string => { return `inshellisense session [${statusMessage}]\n`; }; -export const render = async (shell: Shell, underTest: boolean, parentTermExit: boolean) => { +export const render = async (shell: Shell, underTest: boolean) => { const term = await isterm.spawn({ shell, rows: process.stdout.rows, cols: process.stdout.columns, underTest }); const suggestionManager = new SuggestionManager(term, shell); let hasActiveSuggestions = false; @@ -140,9 +140,6 @@ export const render = async (shell: Shell, underTest: boolean, parentTermExit: b }); term.onExit(({ exitCode }) => { - if (parentTermExit && process.ppid) { - process.kill(process.ppid); - } process.exit(exitCode); }); process.stdout.on("resize", () => { diff --git a/src/utils/shell.ts b/src/utils/shell.ts index dd0890b..317960b 100644 --- a/src/utils/shell.ts +++ b/src/utils/shell.ts @@ -33,6 +33,8 @@ export const supportedShells = [ Shell.Nushell, ].filter((shell) => shell != null) as Shell[]; +export const shellEnvSupportedShells = [Shell.Bash]; + export const userZdotdir = process.env?.ZDOTDIR ?? os.homedir() ?? `~`; export const zdotdir = path.join(os.tmpdir(), `is-zsh`); const configFolder = ".inshellisense"; @@ -119,3 +121,13 @@ export const getPathSeperator = (shell: Shell) => (shell == Shell.Bash || shell // nu fully re-writes the prompt every keystroke resulting in duplicate start/end sequences on the same line export const getShellPromptRewrites = (shell: Shell) => shell == Shell.Nushell; + +export const getShellConfig = (shell: Shell): string => { + switch (shell) { + case Shell.Bash: + return `if [[ -z "\${ISTERM}" && $- = *i* && $- != *c* ]]; then + is -s bash ; exit +fi`; + } + return ""; +}; From e4792f05adfe588abb57993b9f8fb36160eb9f0e Mon Sep 17 00:00:00 2001 From: Chapman Pendery Date: Fri, 12 Apr 2024 14:06:13 -0700 Subject: [PATCH 2/2] fix: use name init Signed-off-by: Chapman Pendery --- README.md | 2 +- src/commands/{shellenv.ts => init.ts} | 4 ++-- src/index.ts | 4 ++-- src/utils/shell.ts | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) rename src/commands/{shellenv.ts => init.ts} (85%) diff --git a/README.md b/README.md index e20aba0..d39b3d1 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ If you'd like to automatically start inshellisense when you open your shell, run ```shell # bash -is shellenv bash >> ~/.bashrc +is init bash >> ~/.bashrc ``` ### Usage diff --git a/src/commands/shellenv.ts b/src/commands/init.ts similarity index 85% rename from src/commands/shellenv.ts rename to src/commands/init.ts index 70f8d1b..a3b28fc 100644 --- a/src/commands/shellenv.ts +++ b/src/commands/init.ts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import { Command } from "commander"; -import { Shell, shellEnvSupportedShells as shells, getShellConfig } from "../utils/shell.js"; +import { Shell, initSupportedShells as shells, getShellConfig } from "../utils/shell.js"; const supportedShells = shells.join(", "); @@ -15,7 +15,7 @@ const action = (program: Command) => async (shell: string) => { process.exit(0); }; -const cmd = new Command("shellenv"); +const cmd = new Command("init"); cmd.description(`generates shell configurations for the provided shell`); cmd.argument("", `shell to generate configuration for, supported shells: ${supportedShells}`); cmd.action(action(cmd)); diff --git a/src/index.ts b/src/index.ts index b03f981..ddb26d7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,7 +9,7 @@ import { Command, Option } from "commander"; import complete from "./commands/complete.js"; import uninstall from "./commands/uninstall.js"; -import shellenv from "./commands/shellenv.js"; +import init from "./commands/init.js"; import { action, supportedShells } from "./commands/root.js"; import { getVersion } from "./utils/version.js"; @@ -34,6 +34,6 @@ program program.addCommand(complete); program.addCommand(uninstall); -program.addCommand(shellenv); +program.addCommand(init); program.parse(); diff --git a/src/utils/shell.ts b/src/utils/shell.ts index 317960b..7c6f3ff 100644 --- a/src/utils/shell.ts +++ b/src/utils/shell.ts @@ -33,7 +33,7 @@ export const supportedShells = [ Shell.Nushell, ].filter((shell) => shell != null) as Shell[]; -export const shellEnvSupportedShells = [Shell.Bash]; +export const initSupportedShells = [Shell.Bash]; export const userZdotdir = process.env?.ZDOTDIR ?? os.homedir() ?? `~`; export const zdotdir = path.join(os.tmpdir(), `is-zsh`);