@microsoft/inshellisense 0.0.1-rc.4 → 0.0.1-rc.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,13 +1,15 @@
1
1
  # inshellisense
2
2
 
3
- `inshellisense` provides IDE style autocomplete for shells. It's a terminal native runtime for [autocomplete](https://github.com/withfig/autocomplete) which has support for 600+ command line tools. `inshellisense` supports Windows, Linux, & MacOS.
3
+ `inshellisense` provides IDE style autocomplete for shells. It's a terminal native runtime for [autocomplete](https://github.com/withfig/autocomplete) which has support for 600+ command line tools. `inshellisense` supports Windows, Linux, & macOS.
4
4
 
5
5
  <p align="center"><img alt="demo of inshellisense working" src="/docs/demo.gif" height="450px"/></p>
6
6
 
7
7
  ## Getting Started
8
8
 
9
9
  ### Requirements
10
+
10
11
  - `node >= 16.x`
12
+ - node-gyp dependencies installed for your platform (see [node-gyp](https://github.com/nodejs/node-gyp) for more details)
11
13
 
12
14
  ### Installation
13
15
 
@@ -17,13 +19,7 @@ npm install -g @microsoft/inshellisense
17
19
 
18
20
  ### Quickstart
19
21
 
20
- After completing the installation, you can already run `inshellisense --shell <shell>` to start the autocomplete session for your desired shell. Additionally, you can bind `inshellisense` to a keybinding of `CTRL+a` by running the below command. This brings the added advantages of automatically starting the autocomplete session with your current shell and injecting any accepted command into your shell's history.
21
-
22
- ```shell
23
- inshellisense bind
24
- ```
25
-
26
- Additionally, inshellisense is also aliased under `is` after install for convenience.
22
+ 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.
27
23
 
28
24
  ## Integrations
29
25
 
@@ -1,41 +1,21 @@
1
1
  // Copyright (c) Microsoft Corporation.
2
2
  // Licensed under the MIT License.
3
- import { initRender } from "../ui/ui-init.js";
4
3
  import { render } from "../ui/ui-root.js";
5
- import { executeShellCommandTTY } from "../runtime/utils.js";
6
- import { saveCommand, loadCommand } from "../utils/cache.js";
7
- import { supportedShells as shells } from "../utils/bindings.js";
4
+ import { Shell, supportedShells as shells, setupZshDotfiles } from "../utils/shell.js";
8
5
  import { inferShell } from "../utils/shell.js";
6
+ import { loadConfig } from "../utils/config.js";
9
7
  export const supportedShells = shells.join(", ");
10
8
  export const action = (program) => async (options) => {
11
- if (options.history) {
12
- process.stdout.write(await loadCommand());
13
- process.exit(0);
9
+ await loadConfig(program);
10
+ const shell = options.shell ?? (await inferShell());
11
+ if (shell == null) {
12
+ program.error(`Unable to identify shell, use the -s/--shell option to provide your shell`, { exitCode: 1 });
14
13
  }
15
- const shell = options.shell ?? (await inferShell()) ?? (await initRender()) ?? "";
16
14
  if (!shells.map((s) => s.valueOf()).includes(shell)) {
17
15
  program.error(`Unsupported shell: '${shell}', supported shells: ${supportedShells}`, { exitCode: 1 });
18
16
  }
19
- let executed = false;
20
- const commands = [];
21
- let result = { code: 0 };
22
- let startingCommand = options.command;
23
- while (options.duration === "session" || !executed) {
24
- const commandToExecute = await render(startingCommand);
25
- if (commandToExecute == null || commandToExecute.trim().toLowerCase() == "exit" || commandToExecute.trim().toLowerCase() == "logout") {
26
- result = { code: 0 };
27
- break;
28
- }
29
- commands.push(commandToExecute);
30
- result = await executeShellCommandTTY(shell, commandToExecute);
31
- executed = true;
32
- startingCommand = undefined;
33
- }
34
- await saveCommand(commands);
35
- if (result.code) {
36
- process.exit(result.code);
37
- }
38
- else {
39
- process.exit(0);
17
+ if (shell == Shell.Zsh) {
18
+ await setupZshDotfiles();
40
19
  }
20
+ await render(shell);
41
21
  };
@@ -6,6 +6,6 @@ const action = async () => {
6
6
  await render();
7
7
  };
8
8
  const cmd = new Command("uninstall");
9
- cmd.description(`removes all bindings and configuration for inshellisense`);
9
+ cmd.description(`removes all configuration for inshellisense`);
10
10
  cmd.action(action);
11
11
  export default cmd;
package/build/index.js CHANGED
@@ -3,7 +3,6 @@
3
3
  // Licensed under the MIT License.
4
4
  /* eslint-disable header/header */
5
5
  import { Command } from "commander";
6
- import bind from "./commands/bind.js";
7
6
  import uninstall from "./commands/uninstall.js";
8
7
  import { action, supportedShells } from "./commands/root.js";
9
8
  import { getVersion } from "./utils/version.js";
@@ -12,12 +11,8 @@ program
12
11
  .name("inshellisense")
13
12
  .description("IDE style command line auto complete")
14
13
  .version(await getVersion(), "-v, --version", "output the current version")
15
- .option("-s, --shell <shell>", `shell to use for command execution, supported shells: ${supportedShells}`)
16
- .option("-c, --command <commmand>", "command to use as initial input")
17
- .option("--history", "get the last command execute")
18
- .option("-d, --duration <duration>", "duration of the autocomplete session, supported durations: single, session", "session")
19
14
  .action(action(program))
15
+ .option("-s, --shell <shell>", `shell to use for command execution, supported shells: ${supportedShells}`)
20
16
  .showHelpAfterError("(add --help for additional information)");
21
- program.addCommand(bind);
22
17
  program.addCommand(uninstall);
23
18
  program.parse();
@@ -0,0 +1,212 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+ import os from "node:os";
4
+ import { Shell } from "../utils/shell.js";
5
+ import log from "../utils/log.js";
6
+ import { getConfig } from "../utils/config.js";
7
+ const maxPromptPollDistance = 10;
8
+ export class CommandManager {
9
+ #activeCommand;
10
+ #previousCommandLines;
11
+ #terminal;
12
+ #shell;
13
+ #supportsProperOscPlacements = os.platform() !== "win32";
14
+ constructor(terminal, shell) {
15
+ this.#terminal = terminal;
16
+ this.#shell = shell;
17
+ this.#activeCommand = {};
18
+ this.#previousCommandLines = new Set();
19
+ if (this.#supportsProperOscPlacements) {
20
+ this.#terminal.parser.registerCsiHandler({ final: "J" }, (params) => {
21
+ if (params.at(0) == 3 || params.at(0) == 2) {
22
+ this.handleClear();
23
+ }
24
+ return false;
25
+ });
26
+ }
27
+ }
28
+ handlePromptStart() {
29
+ this.#activeCommand = { promptStartMarker: this.#terminal.registerMarker(0), hasOutput: false, cursorTerminated: false };
30
+ }
31
+ handlePromptEnd() {
32
+ this.#activeCommand.promptEndMarker = this.#terminal.registerMarker(0);
33
+ if (this.#activeCommand.promptEndMarker?.line === this.#terminal.buffer.active.cursorY) {
34
+ this.#activeCommand.promptEndX = this.#terminal.buffer.active.cursorX;
35
+ }
36
+ if (this.#supportsProperOscPlacements) {
37
+ this.#activeCommand.promptText = this.#terminal.buffer.active.getLine(this.#activeCommand.promptEndMarker?.line ?? 0)?.translateToString(true);
38
+ this.#previousCommandLines.add(this.#activeCommand.promptEndMarker?.line ?? -1);
39
+ }
40
+ }
41
+ handleClear() {
42
+ this.handlePromptStart();
43
+ this.#previousCommandLines = new Set();
44
+ }
45
+ _getWindowsPrompt(y) {
46
+ const line = this.#terminal.buffer.active.getLine(y);
47
+ if (!line) {
48
+ return;
49
+ }
50
+ const lineText = line.translateToString(true);
51
+ if (!lineText) {
52
+ return;
53
+ }
54
+ // User defined prompt
55
+ const inshellisenseConfig = getConfig();
56
+ if (this.#shell == Shell.Bash) {
57
+ if (inshellisenseConfig.promptRegex?.bash != null) {
58
+ const customBashPrompt = lineText.match(new RegExp(inshellisenseConfig.promptRegex?.bash.regex))?.groups?.prompt;
59
+ const adjustedPrompt = this._adjustPrompt(customBashPrompt, lineText, inshellisenseConfig.promptRegex?.bash.postfix);
60
+ if (adjustedPrompt) {
61
+ return adjustedPrompt;
62
+ }
63
+ }
64
+ const bashPrompt = lineText.match(/^(?<prompt>.*\$\s?)/)?.groups?.prompt;
65
+ if (bashPrompt) {
66
+ const adjustedPrompt = this._adjustPrompt(bashPrompt, lineText, "$");
67
+ if (adjustedPrompt) {
68
+ return adjustedPrompt;
69
+ }
70
+ }
71
+ }
72
+ if (this.#shell == Shell.Powershell || this.#shell == Shell.Pwsh) {
73
+ if (inshellisenseConfig.promptRegex?.pwsh != null && this.#shell == Shell.Pwsh) {
74
+ const customPwshPrompt = lineText.match(new RegExp(inshellisenseConfig.promptRegex?.pwsh.regex))?.groups?.prompt;
75
+ const adjustedPrompt = this._adjustPrompt(customPwshPrompt, lineText, inshellisenseConfig.promptRegex?.pwsh.postfix);
76
+ if (adjustedPrompt) {
77
+ return adjustedPrompt;
78
+ }
79
+ }
80
+ if (inshellisenseConfig.promptRegex?.powershell != null && this.#shell == Shell.Powershell) {
81
+ const customPowershellPrompt = lineText.match(new RegExp(inshellisenseConfig.promptRegex?.powershell.regex))?.groups?.prompt;
82
+ const adjustedPrompt = this._adjustPrompt(customPowershellPrompt, lineText, inshellisenseConfig.promptRegex?.powershell.postfix);
83
+ if (adjustedPrompt) {
84
+ return adjustedPrompt;
85
+ }
86
+ }
87
+ const pwshPrompt = lineText.match(/(?<prompt>(\(.+\)\s)?(?:PS.+>\s?))/)?.groups?.prompt;
88
+ if (pwshPrompt) {
89
+ const adjustedPrompt = this._adjustPrompt(pwshPrompt, lineText, ">");
90
+ if (adjustedPrompt) {
91
+ return adjustedPrompt;
92
+ }
93
+ }
94
+ }
95
+ if (this.#shell == Shell.Cmd) {
96
+ return lineText.match(/^(?<prompt>(\(.+\)\s)?(?:[A-Z]:\\.*>))/)?.groups?.prompt;
97
+ }
98
+ // Custom prompts like starship end in the common \u276f character
99
+ const customPrompt = lineText.match(/.*\u276f(?=[^\u276f]*$)/g)?.[0];
100
+ if (customPrompt) {
101
+ const adjustedPrompt = this._adjustPrompt(customPrompt, lineText, "\u276f");
102
+ if (adjustedPrompt) {
103
+ return adjustedPrompt;
104
+ }
105
+ }
106
+ }
107
+ _adjustPrompt(prompt, lineText, char) {
108
+ if (!prompt) {
109
+ return;
110
+ }
111
+ // Conpty may not 'render' the space at the end of the prompt
112
+ if (lineText === prompt && prompt.endsWith(char)) {
113
+ prompt += " ";
114
+ }
115
+ return prompt;
116
+ }
117
+ _isSuggestion(cell) {
118
+ const color = cell?.getFgColor();
119
+ const dullColor = color == 8 || (color ?? 0) > 235;
120
+ if (this.#shell == Shell.Powershell) {
121
+ return false;
122
+ }
123
+ else if (this.#shell == Shell.Pwsh) {
124
+ return (color ?? 0) > 235;
125
+ }
126
+ return dullColor;
127
+ }
128
+ getState() {
129
+ return {
130
+ promptText: this.#activeCommand.promptText,
131
+ commandText: this.#activeCommand.commandText,
132
+ suggestionsText: this.#activeCommand.suggestionsText,
133
+ hasOutput: this.#activeCommand.hasOutput,
134
+ cursorTerminated: this.#activeCommand.cursorTerminated,
135
+ };
136
+ }
137
+ termSync() {
138
+ if (this.#activeCommand.promptEndMarker == null || this.#activeCommand.promptStartMarker == null) {
139
+ return;
140
+ }
141
+ const promptEndMarker = this.#activeCommand.promptEndMarker;
142
+ const promptStartMarker = this.#activeCommand.promptStartMarker;
143
+ const globalCursorPosition = this.#terminal.buffer.active.baseY + this.#terminal.buffer.active.cursorY;
144
+ const withinPollDistance = globalCursorPosition < this.#activeCommand.promptEndMarker.line + 5;
145
+ if (globalCursorPosition < promptStartMarker.line) {
146
+ this.handleClear();
147
+ }
148
+ // if we haven't fond the prompt yet, poll over the next 5 lines searching for it
149
+ if (this.#activeCommand.promptText == null && withinPollDistance) {
150
+ for (let i = globalCursorPosition; i < promptEndMarker.line + maxPromptPollDistance; i++) {
151
+ if (this.#previousCommandLines.has(i))
152
+ continue;
153
+ const promptResult = this._getWindowsPrompt(i);
154
+ if (promptResult != null) {
155
+ this.#activeCommand.promptEndMarker = this.#terminal.registerMarker(i - globalCursorPosition);
156
+ this.#activeCommand.promptEndX = promptResult.length;
157
+ this.#activeCommand.promptText = promptResult;
158
+ this.#previousCommandLines.add(i);
159
+ }
160
+ }
161
+ }
162
+ // if the prompt is set, now parse out the values from the terminal
163
+ if (this.#activeCommand.promptText != null) {
164
+ let lineY = promptEndMarker.line;
165
+ let line = this.#terminal.buffer.active.getLine(promptEndMarker.line);
166
+ let command = "";
167
+ let suggestions = "";
168
+ for (;;) {
169
+ for (let i = lineY == promptEndMarker.line ? this.#activeCommand.promptText.length : 0; i < this.#terminal.cols; i++) {
170
+ const cell = line?.getCell(i);
171
+ if (cell == null)
172
+ continue;
173
+ if (!this._isSuggestion(cell) && suggestions.length == 0) {
174
+ command += cell.getChars();
175
+ }
176
+ else {
177
+ suggestions += cell.getChars();
178
+ }
179
+ }
180
+ lineY += 1;
181
+ line = this.#terminal.buffer.active.getLine(lineY);
182
+ if (!line?.isWrapped) {
183
+ break;
184
+ }
185
+ }
186
+ const cursorAtEndOfInput = (this.#activeCommand.promptText.length + command.trim().length) % this.#terminal.cols <= this.#terminal.buffer.active.cursorX;
187
+ let hasOutput = false;
188
+ let cell = undefined;
189
+ for (let i = 0; i < this.#terminal.cols; i++) {
190
+ cell = line?.getCell(i, cell);
191
+ if (cell == null)
192
+ continue;
193
+ hasOutput = cell.getChars() != "";
194
+ if (hasOutput) {
195
+ break;
196
+ }
197
+ }
198
+ const commandPostfix = this.#activeCommand.promptText.length + command.trim().length < this.#terminal.buffer.active.cursorX ? " " : "";
199
+ this.#activeCommand.persistentOutput = this.#activeCommand.hasOutput && hasOutput;
200
+ this.#activeCommand.hasOutput = hasOutput;
201
+ this.#activeCommand.suggestionsText = suggestions.trim();
202
+ this.#activeCommand.commandText = command.trim() + commandPostfix;
203
+ this.#activeCommand.cursorTerminated = cursorAtEndOfInput;
204
+ }
205
+ log.debug({
206
+ msg: "cmd manager state",
207
+ ...this.#activeCommand,
208
+ promptEndMarker: this.#activeCommand.promptEndMarker?.line,
209
+ promptStartMarker: this.#activeCommand.promptStartMarker?.line,
210
+ });
211
+ }
212
+ }
@@ -0,0 +1,4 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+ import { spawn } from "./pty.js";
4
+ export default { spawn };
@@ -0,0 +1,217 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+ import { EventEmitter } from "node:events";
4
+ import process from "node:process";
5
+ import os from "node:os";
6
+ import path from "node:path";
7
+ import url from "node:url";
8
+ import pty from "node-pty";
9
+ import { Shell, userZdotdir, zdotdir } from "../utils/shell.js";
10
+ import { IsTermOscPs, IstermOscPt, IstermPromptStart, IstermPromptEnd } from "../utils/ansi.js";
11
+ import xterm from "xterm-headless";
12
+ import { CommandManager } from "./commandManager.js";
13
+ import log from "../utils/log.js";
14
+ import { gitBashPath } from "../utils/shell.js";
15
+ import ansi from "ansi-escapes";
16
+ import styles from "ansi-styles";
17
+ const ISTermOnDataEvent = "data";
18
+ export class ISTerm {
19
+ pid;
20
+ cols;
21
+ rows;
22
+ process;
23
+ handleFlowControl = false;
24
+ onData;
25
+ onExit;
26
+ shellBuffer;
27
+ #pty;
28
+ #ptyEmitter;
29
+ #term;
30
+ #commandManager;
31
+ constructor({ shell, cols, rows, env, shellTarget, shellArgs }) {
32
+ this.#pty = pty.spawn(shellTarget, shellArgs ?? [], {
33
+ name: "xterm-256color",
34
+ cols,
35
+ rows,
36
+ cwd: process.cwd(),
37
+ env: { ...convertToPtyEnv(shell), ...env },
38
+ });
39
+ this.pid = this.#pty.pid;
40
+ this.cols = this.#pty.cols;
41
+ this.rows = this.#pty.rows;
42
+ this.process = this.#pty.process;
43
+ this.#term = new xterm.Terminal({ allowProposedApi: true, rows, cols });
44
+ this.#term.parser.registerOscHandler(IsTermOscPs, (data) => this._handleIsSequence(data));
45
+ this.#commandManager = new CommandManager(this.#term, shell);
46
+ this.#ptyEmitter = new EventEmitter();
47
+ this.#pty.onData((data) => {
48
+ this.#term.write(data, () => {
49
+ log.debug({ msg: "parsing data", data, bytes: Uint8Array.from([...data].map((c) => c.charCodeAt(0))) });
50
+ this.#commandManager.termSync();
51
+ this.#ptyEmitter.emit(ISTermOnDataEvent, data);
52
+ });
53
+ });
54
+ this.onData = (listener) => {
55
+ this.#ptyEmitter.on(ISTermOnDataEvent, listener);
56
+ return {
57
+ dispose: () => this.#ptyEmitter.removeListener(ISTermOnDataEvent, listener),
58
+ };
59
+ };
60
+ this.onExit = this.#pty.onExit;
61
+ }
62
+ _handleIsSequence(data) {
63
+ const argsIndex = data.indexOf(";");
64
+ const sequence = argsIndex === -1 ? data : data.substring(0, argsIndex);
65
+ switch (sequence) {
66
+ case IstermOscPt.PromptStarted:
67
+ this.#commandManager.handlePromptStart();
68
+ break;
69
+ case IstermOscPt.PromptEnded:
70
+ this.#commandManager.handlePromptEnd();
71
+ break;
72
+ default:
73
+ return false;
74
+ }
75
+ return true;
76
+ }
77
+ noop() {
78
+ this.#ptyEmitter.emit(ISTermOnDataEvent, "");
79
+ }
80
+ resize(columns, rows) {
81
+ this.cols = columns;
82
+ this.rows = rows;
83
+ this.#pty.resize(columns, rows);
84
+ this.#term.resize(columns, rows);
85
+ }
86
+ clear() {
87
+ this.#term.reset();
88
+ this.#pty.clear();
89
+ }
90
+ kill(signal) {
91
+ this.#pty.kill(signal);
92
+ }
93
+ pause() {
94
+ this.#pty.pause();
95
+ }
96
+ resume() {
97
+ this.#pty.resume();
98
+ }
99
+ write(data) {
100
+ log.debug({ msg: "reading data", data, bytes: Uint8Array.from([...data].map((c) => c.charCodeAt(0))) });
101
+ this.#pty.write(data);
102
+ }
103
+ getCommandState() {
104
+ return this.#commandManager.getState();
105
+ }
106
+ getCursorState() {
107
+ return {
108
+ onLastLine: this.#term.buffer.active.cursorY >= this.#term.rows - 2,
109
+ remainingLines: Math.max(this.#term.rows - 2 - this.#term.buffer.active.cursorY, 0),
110
+ cursorX: this.#term.buffer.active.cursorX,
111
+ cursorY: this.#term.buffer.active.cursorY,
112
+ };
113
+ }
114
+ _sameColor(baseCell, targetCell) {
115
+ return (baseCell?.getBgColorMode() == targetCell?.getBgColorMode() &&
116
+ baseCell?.getBgColor() == targetCell?.getBgColor() &&
117
+ baseCell?.getFgColorMode() == targetCell?.getFgColorMode() &&
118
+ baseCell?.getFgColor() == targetCell?.getFgColor());
119
+ }
120
+ _getAnsiColors(cell) {
121
+ if (cell == null)
122
+ return "";
123
+ let bgAnsi = "";
124
+ cell.getBgColor;
125
+ cell.getFgColor;
126
+ if (cell.isBgDefault()) {
127
+ bgAnsi = "\x1b[49m";
128
+ }
129
+ else if (cell.isBgPalette()) {
130
+ bgAnsi = `\x1b[48;5;${cell.getBgColor()}m`;
131
+ }
132
+ else {
133
+ bgAnsi = `\x1b[48;5;${styles.hexToAnsi256(cell.getBgColor().toString(16))}m`;
134
+ }
135
+ let fgAnsi = "";
136
+ if (cell.isFgDefault()) {
137
+ fgAnsi = "\x1b[39m";
138
+ }
139
+ else if (cell.isFgPalette()) {
140
+ fgAnsi = `\x1b[38;5;${cell.getFgColor()}m`;
141
+ }
142
+ else {
143
+ fgAnsi = `\x1b[38;5;${styles.hexToAnsi256(cell.getFgColor().toString(16))}m`;
144
+ }
145
+ return bgAnsi + fgAnsi;
146
+ }
147
+ getCells(height, direction) {
148
+ const currentCursorPosition = this.#term.buffer.active.cursorY + this.#term.buffer.active.baseY;
149
+ const writeLine = (y) => {
150
+ const line = this.#term.buffer.active.getLine(y);
151
+ const ansiLine = ["\x1b[0m"];
152
+ if (line == null)
153
+ return "";
154
+ let prevCell;
155
+ for (let x = 0; x < line.length; x++) {
156
+ const cell = line.getCell(x);
157
+ const chars = cell?.getChars() ?? "";
158
+ if (!this._sameColor(prevCell, cell)) {
159
+ ansiLine.push(this._getAnsiColors(cell));
160
+ }
161
+ ansiLine.push(chars == "" ? " " : chars);
162
+ prevCell = cell;
163
+ }
164
+ return ansiLine.join("");
165
+ };
166
+ const lines = [];
167
+ if (direction == "above") {
168
+ const startCursorPosition = currentCursorPosition - 1;
169
+ const endCursorPosition = currentCursorPosition - 1 - height;
170
+ for (let y = startCursorPosition; y > endCursorPosition; y--) {
171
+ lines.push(writeLine(y));
172
+ }
173
+ }
174
+ else {
175
+ const startCursorPosition = currentCursorPosition + 1;
176
+ const endCursorPosition = currentCursorPosition + 1 + height;
177
+ for (let y = startCursorPosition; y < endCursorPosition; y++) {
178
+ lines.push(writeLine(y));
179
+ }
180
+ }
181
+ return lines.reverse().join(ansi.cursorNextLine);
182
+ }
183
+ }
184
+ export const spawn = async (options) => {
185
+ const { shellTarget, shellArgs } = await convertToPtyTarget(options.shell);
186
+ return new ISTerm({ ...options, shellTarget, shellArgs });
187
+ };
188
+ const convertToPtyTarget = async (shell) => {
189
+ const platform = os.platform();
190
+ const shellTarget = shell == Shell.Bash && platform == "win32" ? await gitBashPath() : platform == "win32" ? `${shell}.exe` : shell;
191
+ const shellFolderPath = path.join(path.dirname(url.fileURLToPath(import.meta.url)), "..", "..", "shell");
192
+ let shellArgs = [];
193
+ switch (shell) {
194
+ case Shell.Bash:
195
+ shellArgs = ["--init-file", path.join(shellFolderPath, "shellIntegration.bash")];
196
+ break;
197
+ case (Shell.Powershell, Shell.Pwsh):
198
+ shellArgs = ["-noexit", "-command", `try { . "${path.join(shellFolderPath, "shellIntegration.ps1")}" } catch {}`];
199
+ break;
200
+ case Shell.Fish:
201
+ shellArgs = ["--init-command", `. ${path.join(shellFolderPath, "shellIntegration.fish").replace(/(\s+)/g, "\\$1")}`];
202
+ break;
203
+ }
204
+ return { shellTarget, shellArgs };
205
+ };
206
+ const convertToPtyEnv = (shell) => {
207
+ switch (shell) {
208
+ case Shell.Cmd: {
209
+ const prompt = process.env.PROMPT ? process.env.PROMPT : "$P$G";
210
+ return { ...process.env, PROMPT: `${IstermPromptStart}${prompt}${IstermPromptEnd}` };
211
+ }
212
+ case Shell.Zsh: {
213
+ return { ...process.env, ZDOTDIR: zdotdir, USER_ZDOTDIR: userZdotdir };
214
+ }
215
+ }
216
+ return process.env;
217
+ };
@@ -1,6 +1,6 @@
1
1
  // Copyright (c) Microsoft Corporation.
2
2
  // Licensed under the MIT License.
3
- import fsAsync from "fs/promises";
3
+ import fsAsync from "node:fs/promises";
4
4
  import process from "node:process";
5
5
  const filepathsTemplate = async () => {
6
6
  const files = await fsAsync.readdir(process.cwd(), { withFileTypes: true });
package/build/ui/input.js CHANGED
@@ -1,55 +1,9 @@
1
1
  // Copyright (c) Microsoft Corporation.
2
2
  // Licensed under the MIT License.
3
- import React, { useState, useEffect } from "react";
4
- import { useInput, Text } from "ink";
5
- import chalk from "chalk";
6
- const BlinkSpeed = 530;
7
- const CursorColor = "#FFFFFF";
8
- export default function Input({ value, setValue, prompt, activeSuggestion, tabCompletionDropSize, }) {
9
- const [cursorLocation, setCursorLocation] = useState(value.length);
10
- const [cursorBlink, setCursorBlink] = useState(true);
11
- useEffect(() => {
12
- setTimeout(() => {
13
- setCursorBlink(!cursorBlink);
14
- }, BlinkSpeed);
15
- }, [cursorBlink]);
16
- // TODO: arrow key navigation shortcuts (emacs & vim modes)
17
- useInput((input, key) => {
18
- // TODO: handle delete better on unix systems: https://github.com/vadimdemedes/ink/issues/634
19
- const windows = process.platform === "win32";
20
- const backspaceKey = windows ? key.backspace : key.backspace || key.delete;
21
- const deleteKey = windows ? key.delete : false;
22
- if (backspaceKey) {
23
- setValue([...value].slice(0, Math.max(cursorLocation - 1, 0)).join("") + [...value].slice(cursorLocation).join(""));
24
- setCursorLocation(Math.max(cursorLocation - 1, 0));
25
- }
26
- else if (deleteKey) {
27
- setValue([...value].slice(0, cursorLocation).join("") + [...value].slice(Math.min(value.length, cursorLocation + 1)).join(""));
28
- }
29
- else if (key.leftArrow) {
30
- setCursorLocation(Math.max(cursorLocation - 1, 0));
31
- }
32
- else if (key.rightArrow) {
33
- setCursorLocation(Math.min(cursorLocation + 1, value.length));
34
- }
35
- else if (key.tab) {
36
- if (activeSuggestion) {
37
- // TOOD: support insertValue
38
- const newValue = [...value].slice(0, cursorLocation - tabCompletionDropSize).join("") + activeSuggestion.name + " ";
39
- setValue(newValue);
40
- setCursorLocation(newValue.length);
41
- }
42
- }
43
- else if (input) {
44
- setValue([...value].slice(0, cursorLocation).join("") + input + [...value].slice(cursorLocation).join(""));
45
- setCursorLocation(cursorLocation + input.length);
46
- }
47
- });
48
- const cursoredCommand = value + " ";
49
- const cursoredText = [...cursoredCommand].slice(0, cursorLocation).join("") +
50
- (cursorBlink ? chalk.bgHex(CursorColor).inverse([...cursoredCommand].at(cursorLocation)) : [...cursoredCommand].at(cursorLocation)) +
51
- [...cursoredCommand].slice(cursorLocation + 1).join("");
52
- return (React.createElement(Text, null,
53
- prompt,
54
- cursoredText));
55
- }
3
+ export const inputModifier = (input) => {
4
+ switch (input.toString()) {
5
+ case "\b":
6
+ return "\u007F"; // DEL
7
+ }
8
+ return input.toString();
9
+ };