@microsoft/inshellisense 0.0.1-rc.6 → 0.0.1-rc.8
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 +1 -1
- package/build/commands/root.js +1 -1
- package/build/index.js +7 -1
- package/build/isterm/commandManager.js +13 -10
- package/build/isterm/pty.js +14 -5
- package/build/runtime/runtime.js +7 -4
- package/build/ui/suggestionManager.js +22 -10
- package/build/ui/ui-root.js +25 -15
- package/build/utils/ansi.js +1 -24
- package/package.json +19 -5
- package/shell/shellIntegration-rc.zsh +8 -2
- package/shell/shellIntegration.bash +3 -0
- package/shell/shellIntegration.fish +5 -0
- package/shell/shellIntegration.ps1 +7 -0
- package/build/ui/input.js +0 -9
package/README.md
CHANGED
package/build/commands/root.js
CHANGED
package/build/index.js
CHANGED
|
@@ -2,12 +2,17 @@
|
|
|
2
2
|
// Copyright (c) Microsoft Corporation.
|
|
3
3
|
// Licensed under the MIT License.
|
|
4
4
|
/* eslint-disable header/header */
|
|
5
|
-
import { Command } from "commander";
|
|
5
|
+
import { Command, Option } from "commander";
|
|
6
6
|
import complete from "./commands/complete.js";
|
|
7
7
|
import uninstall from "./commands/uninstall.js";
|
|
8
8
|
import { action, supportedShells } from "./commands/root.js";
|
|
9
9
|
import { getVersion } from "./utils/version.js";
|
|
10
10
|
const program = new Command();
|
|
11
|
+
const hiddenOption = (flags, description) => {
|
|
12
|
+
const option = new Option(flags, description);
|
|
13
|
+
option.hidden = true;
|
|
14
|
+
return option;
|
|
15
|
+
};
|
|
11
16
|
program
|
|
12
17
|
.name("inshellisense")
|
|
13
18
|
.description("IDE style command line auto complete")
|
|
@@ -15,6 +20,7 @@ program
|
|
|
15
20
|
.action(action(program))
|
|
16
21
|
.option("-s, --shell <shell>", `shell to use for command execution, supported shells: ${supportedShells}`)
|
|
17
22
|
.option("-c, --check", `check if shell is in an inshellisense session`)
|
|
23
|
+
.addOption(hiddenOption("-T, --test", "used to make e2e tests reproducible across machines"))
|
|
18
24
|
.option("-V, --verbose", `enable verbose logging`)
|
|
19
25
|
.showHelpAfterError("(add --help for additional information)");
|
|
20
26
|
program.addCommand(complete);
|
|
@@ -96,7 +96,7 @@ export class CommandManager {
|
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
if (this.#shell == Shell.Cmd) {
|
|
99
|
-
return lineText.match(/^(?<prompt>(\(.+\)\s)?(?:[A-Z]:\\.*>))/)?.groups?.prompt;
|
|
99
|
+
return lineText.match(/^(?<prompt>(\(.+\)\s)?(?:[A-Z]:\\.*>)|(> ))/)?.groups?.prompt;
|
|
100
100
|
}
|
|
101
101
|
// Custom prompts like starship end in the common \u276f character
|
|
102
102
|
const customPrompt = lineText.match(/.*\u276f(?=[^\u276f]*$)/g)?.[0];
|
|
@@ -119,12 +119,15 @@ export class CommandManager {
|
|
|
119
119
|
}
|
|
120
120
|
_isSuggestion(cell) {
|
|
121
121
|
const color = cell?.getFgColor();
|
|
122
|
-
const
|
|
122
|
+
const dim = (cell?.isDim() ?? 0) > 0;
|
|
123
|
+
const italic = (cell?.isItalic() ?? 0) > 0;
|
|
124
|
+
const dullColor = color == 8 || color == 7 || (color ?? 0) > 235 || (color == 15 && dim);
|
|
125
|
+
const dullItalic = (color ?? 0) > 235 || (dullColor && italic);
|
|
123
126
|
if (this.#shell == Shell.Powershell) {
|
|
124
127
|
return false;
|
|
125
128
|
}
|
|
126
129
|
else if (this.#shell == Shell.Pwsh) {
|
|
127
|
-
return
|
|
130
|
+
return dullItalic;
|
|
128
131
|
}
|
|
129
132
|
return dullColor;
|
|
130
133
|
}
|
|
@@ -141,16 +144,15 @@ export class CommandManager {
|
|
|
141
144
|
if (this.#activeCommand.promptEndMarker == null || this.#activeCommand.promptStartMarker == null) {
|
|
142
145
|
return;
|
|
143
146
|
}
|
|
144
|
-
const promptEndMarker = this.#activeCommand.promptEndMarker;
|
|
145
|
-
const promptStartMarker = this.#activeCommand.promptStartMarker;
|
|
146
147
|
const globalCursorPosition = this.#terminal.buffer.active.baseY + this.#terminal.buffer.active.cursorY;
|
|
147
148
|
const withinPollDistance = globalCursorPosition < this.#activeCommand.promptEndMarker.line + 5;
|
|
148
|
-
if (globalCursorPosition < promptStartMarker.line) {
|
|
149
|
+
if (globalCursorPosition < this.#activeCommand.promptStartMarker.line) {
|
|
149
150
|
this.handleClear();
|
|
151
|
+
this.#activeCommand.promptEndMarker = this.#terminal.registerMarker(0);
|
|
150
152
|
}
|
|
151
153
|
// if we haven't fond the prompt yet, poll over the next 5 lines searching for it
|
|
152
154
|
if (this.#activeCommand.promptText == null && withinPollDistance) {
|
|
153
|
-
for (let i = globalCursorPosition; i < promptEndMarker.line + maxPromptPollDistance; i++) {
|
|
155
|
+
for (let i = globalCursorPosition; i < this.#activeCommand.promptEndMarker.line + maxPromptPollDistance; i++) {
|
|
154
156
|
if (this.#previousCommandLines.has(i))
|
|
155
157
|
continue;
|
|
156
158
|
const promptResult = this._getWindowsPrompt(i);
|
|
@@ -159,17 +161,18 @@ export class CommandManager {
|
|
|
159
161
|
this.#activeCommand.promptEndX = promptResult.length;
|
|
160
162
|
this.#activeCommand.promptText = promptResult;
|
|
161
163
|
this.#previousCommandLines.add(i);
|
|
164
|
+
break;
|
|
162
165
|
}
|
|
163
166
|
}
|
|
164
167
|
}
|
|
165
168
|
// if the prompt is set, now parse out the values from the terminal
|
|
166
169
|
if (this.#activeCommand.promptText != null) {
|
|
167
|
-
let lineY = promptEndMarker.line;
|
|
168
|
-
let line = this.#terminal.buffer.active.getLine(promptEndMarker.line);
|
|
170
|
+
let lineY = this.#activeCommand.promptEndMarker.line;
|
|
171
|
+
let line = this.#terminal.buffer.active.getLine(this.#activeCommand.promptEndMarker.line);
|
|
169
172
|
let command = "";
|
|
170
173
|
let suggestions = "";
|
|
171
174
|
for (;;) {
|
|
172
|
-
for (let i = lineY == promptEndMarker.line ? this.#activeCommand.promptText.length : 0; i < this.#terminal.cols; i++) {
|
|
175
|
+
for (let i = lineY == this.#activeCommand.promptEndMarker.line ? this.#activeCommand.promptText.length : 0; i < this.#terminal.cols; i++) {
|
|
173
176
|
const cell = line?.getCell(i);
|
|
174
177
|
if (cell == null)
|
|
175
178
|
continue;
|
package/build/isterm/pty.js
CHANGED
|
@@ -5,7 +5,7 @@ import process from "node:process";
|
|
|
5
5
|
import os from "node:os";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import url from "node:url";
|
|
8
|
-
import pty from "node-pty";
|
|
8
|
+
import pty from "@homebridge/node-pty-prebuilt-multiarch";
|
|
9
9
|
import { Shell, userZdotdir, zdotdir } from "../utils/shell.js";
|
|
10
10
|
import { IsTermOscPs, IstermOscPt, IstermPromptStart, IstermPromptEnd } from "../utils/ansi.js";
|
|
11
11
|
import xterm from "xterm-headless";
|
|
@@ -30,13 +30,13 @@ export class ISTerm {
|
|
|
30
30
|
#term;
|
|
31
31
|
#commandManager;
|
|
32
32
|
#shell;
|
|
33
|
-
constructor({ shell, cols, rows, env, shellTarget, shellArgs }) {
|
|
33
|
+
constructor({ shell, cols, rows, env, shellTarget, shellArgs, underTest }) {
|
|
34
34
|
this.#pty = pty.spawn(shellTarget, shellArgs ?? [], {
|
|
35
35
|
name: "xterm-256color",
|
|
36
36
|
cols,
|
|
37
37
|
rows,
|
|
38
38
|
cwd: process.cwd(),
|
|
39
|
-
env: { ...convertToPtyEnv(shell), ...env },
|
|
39
|
+
env: { ...convertToPtyEnv(shell, underTest), ...env },
|
|
40
40
|
});
|
|
41
41
|
this.pid = this.#pty.pid;
|
|
42
42
|
this.cols = this.#pty.cols;
|
|
@@ -62,6 +62,10 @@ export class ISTerm {
|
|
|
62
62
|
};
|
|
63
63
|
this.onExit = this.#pty.onExit;
|
|
64
64
|
}
|
|
65
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
66
|
+
on(_event, _listener) {
|
|
67
|
+
throw new Error("Method not implemented as deprecated in node-pty.");
|
|
68
|
+
}
|
|
65
69
|
_deserializeIsMessage(message) {
|
|
66
70
|
return message.replaceAll(/\\(\\|x([0-9a-f]{2}))/gi, (_match, op, hex) => (hex ? String.fromCharCode(parseInt(hex, 16)) : op));
|
|
67
71
|
}
|
|
@@ -221,7 +225,8 @@ const convertToPtyTarget = async (shell) => {
|
|
|
221
225
|
case Shell.Bash:
|
|
222
226
|
shellArgs = ["--init-file", path.join(shellFolderPath, "shellIntegration.bash")];
|
|
223
227
|
break;
|
|
224
|
-
case
|
|
228
|
+
case Shell.Powershell:
|
|
229
|
+
case Shell.Pwsh:
|
|
225
230
|
shellArgs = ["-noexit", "-command", `try { . "${path.join(shellFolderPath, "shellIntegration.ps1")}" } catch {}`];
|
|
226
231
|
break;
|
|
227
232
|
case Shell.Fish:
|
|
@@ -230,13 +235,17 @@ const convertToPtyTarget = async (shell) => {
|
|
|
230
235
|
}
|
|
231
236
|
return { shellTarget, shellArgs };
|
|
232
237
|
};
|
|
233
|
-
const convertToPtyEnv = (shell) => {
|
|
238
|
+
const convertToPtyEnv = (shell, underTest) => {
|
|
234
239
|
const env = {
|
|
235
240
|
...process.env,
|
|
236
241
|
ISTERM: "1",
|
|
242
|
+
ISTERM_TESTING: underTest ? "1" : undefined,
|
|
237
243
|
};
|
|
238
244
|
switch (shell) {
|
|
239
245
|
case Shell.Cmd: {
|
|
246
|
+
if (underTest) {
|
|
247
|
+
return { ...env, PROMPT: `${IstermPromptStart}$G ${IstermPromptEnd}` };
|
|
248
|
+
}
|
|
240
249
|
const prompt = process.env.PROMPT ? process.env.PROMPT : "$P$G";
|
|
241
250
|
return { ...env, PROMPT: `${IstermPromptStart}${prompt}${IstermPromptEnd}` };
|
|
242
251
|
}
|
package/build/runtime/runtime.js
CHANGED
|
@@ -14,6 +14,9 @@ speclist.forEach((s) => {
|
|
|
14
14
|
let activeSet = specSet;
|
|
15
15
|
const specRoutes = s.split("/");
|
|
16
16
|
specRoutes.forEach((route, idx) => {
|
|
17
|
+
if (typeof activeSet !== "object") {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
17
20
|
if (idx === specRoutes.length - 1) {
|
|
18
21
|
const prefix = versionedSpeclist.includes(s) ? "/index.js" : `.js`;
|
|
19
22
|
activeSet[route] = `@withfig/autocomplete/build/${s}${prefix}`;
|
|
@@ -93,12 +96,12 @@ const getSubcommand = (spec) => {
|
|
|
93
96
|
};
|
|
94
97
|
const executeShellCommand = buildExecuteShellCommand(5000);
|
|
95
98
|
const genSubcommand = async (command, parentCommand) => {
|
|
96
|
-
|
|
97
|
-
if (subcommandIdx == null)
|
|
99
|
+
if (!parentCommand.subcommands || parentCommand.subcommands.length === 0)
|
|
98
100
|
return;
|
|
99
|
-
const
|
|
100
|
-
if (
|
|
101
|
+
const subcommandIdx = parentCommand.subcommands.findIndex((s) => (Array.isArray(s.name) ? s.name.includes(command) : s.name === command));
|
|
102
|
+
if (subcommandIdx === -1)
|
|
101
103
|
return;
|
|
104
|
+
const subcommand = parentCommand.subcommands[subcommandIdx];
|
|
102
105
|
// this pulls in the spec from the load spec and overwrites the subcommand in the parent with the loaded spec.
|
|
103
106
|
// then it returns the subcommand and clears the loadSpec field so that it doesn't get called again
|
|
104
107
|
switch (typeof subcommand.loadSpec) {
|
|
@@ -4,7 +4,7 @@ import { getSuggestions } from "../runtime/runtime.js";
|
|
|
4
4
|
import { renderBox, truncateText, truncateMultilineText } from "./utils.js";
|
|
5
5
|
import ansi from "ansi-escapes";
|
|
6
6
|
import chalk from "chalk";
|
|
7
|
-
import
|
|
7
|
+
import log from "../utils/log.js";
|
|
8
8
|
const maxSuggestions = 5;
|
|
9
9
|
const suggestionWidth = 40;
|
|
10
10
|
const descriptionWidth = 30;
|
|
@@ -29,6 +29,7 @@ export class SuggestionManager {
|
|
|
29
29
|
const commandText = this.#term.getCommandState().commandText;
|
|
30
30
|
if (!commandText) {
|
|
31
31
|
this.#suggestBlob = undefined;
|
|
32
|
+
this.#activeSuggestionIdx = 0;
|
|
32
33
|
return;
|
|
33
34
|
}
|
|
34
35
|
if (commandText == this.#command) {
|
|
@@ -37,6 +38,7 @@ export class SuggestionManager {
|
|
|
37
38
|
this.#command = commandText;
|
|
38
39
|
const suggestionBlob = await getSuggestions(commandText, this.#term.cwd, this.#shell);
|
|
39
40
|
this.#suggestBlob = suggestionBlob;
|
|
41
|
+
this.#activeSuggestionIdx = 0;
|
|
40
42
|
}
|
|
41
43
|
_renderArgumentDescription(description, x) {
|
|
42
44
|
if (!description)
|
|
@@ -60,10 +62,15 @@ export class SuggestionManager {
|
|
|
60
62
|
return idx == activeSuggestionIdx ? chalk.bgHex(activeSuggestionBackgroundColor)(truncatedSuggestion) : truncatedSuggestion;
|
|
61
63
|
}), suggestionWidth, x);
|
|
62
64
|
}
|
|
65
|
+
validate(suggestion) {
|
|
66
|
+
const commandText = this.#term.getCommandState().commandText;
|
|
67
|
+
return !commandText ? { data: "", rows: 0 } : suggestion;
|
|
68
|
+
}
|
|
63
69
|
async render(remainingLines) {
|
|
64
70
|
await this._loadSuggestions();
|
|
65
|
-
if (!this.#suggestBlob)
|
|
71
|
+
if (!this.#suggestBlob) {
|
|
66
72
|
return { data: "", rows: 0 };
|
|
73
|
+
}
|
|
67
74
|
const { suggestions, argumentDescription } = this.#suggestBlob;
|
|
68
75
|
const page = Math.min(Math.floor(this.#activeSuggestionIdx / maxSuggestions) + 1, Math.floor(suggestions.length / maxSuggestions) + 1);
|
|
69
76
|
const pagedSuggestions = suggestions.filter((_, idx) => idx < page * maxSuggestions && idx >= (page - 1) * maxSuggestions);
|
|
@@ -112,20 +119,21 @@ export class SuggestionManager {
|
|
|
112
119
|
rows,
|
|
113
120
|
};
|
|
114
121
|
}
|
|
115
|
-
update(
|
|
116
|
-
const
|
|
117
|
-
if (
|
|
122
|
+
update(keyPress) {
|
|
123
|
+
const { name } = keyPress;
|
|
124
|
+
if (!this.#suggestBlob) {
|
|
118
125
|
return false;
|
|
119
|
-
|
|
126
|
+
}
|
|
127
|
+
if (name == "escape") {
|
|
120
128
|
this.#suggestBlob = undefined;
|
|
121
129
|
}
|
|
122
|
-
else if (
|
|
130
|
+
else if (name == "up") {
|
|
123
131
|
this.#activeSuggestionIdx = Math.max(0, this.#activeSuggestionIdx - 1);
|
|
124
132
|
}
|
|
125
|
-
else if (
|
|
133
|
+
else if (name == "down") {
|
|
126
134
|
this.#activeSuggestionIdx = Math.min(this.#activeSuggestionIdx + 1, (this.#suggestBlob?.suggestions.length ?? 1) - 1);
|
|
127
135
|
}
|
|
128
|
-
else if (
|
|
136
|
+
else if (name == "tab") {
|
|
129
137
|
const removals = "\u007F".repeat(this.#suggestBlob?.charactersToDrop ?? 0);
|
|
130
138
|
const suggestion = this.#suggestBlob?.suggestions.at(this.#activeSuggestionIdx);
|
|
131
139
|
const chars = suggestion?.insertValue ?? suggestion?.name + " ";
|
|
@@ -134,6 +142,10 @@ export class SuggestionManager {
|
|
|
134
142
|
}
|
|
135
143
|
this.#term.write(removals + chars);
|
|
136
144
|
}
|
|
137
|
-
|
|
145
|
+
else {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
log.debug({ msg: "handled keypress", ...keyPress });
|
|
149
|
+
return true;
|
|
138
150
|
}
|
|
139
151
|
}
|
package/build/ui/ui-root.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
|
2
2
|
// Licensed under the MIT License.
|
|
3
|
+
import readline from "node:readline";
|
|
3
4
|
import ansi from "ansi-escapes";
|
|
4
5
|
import chalk from "chalk";
|
|
5
|
-
import { inputModifier } from "./input.js";
|
|
6
6
|
import log from "../utils/log.js";
|
|
7
|
+
import { Shell } from "../utils/shell.js";
|
|
7
8
|
import isterm from "../isterm/index.js";
|
|
8
9
|
import { eraseLinesBelow } from "../utils/ansi.js";
|
|
9
10
|
import { SuggestionManager, MAX_LINES } from "./suggestionManager.js";
|
|
@@ -11,12 +12,14 @@ export const renderConfirmation = (live) => {
|
|
|
11
12
|
const statusMessage = live ? chalk.green("live") : chalk.red("not found");
|
|
12
13
|
return `inshellisense session [${statusMessage}]\n`;
|
|
13
14
|
};
|
|
14
|
-
export const render = async (shell) => {
|
|
15
|
-
const term = await isterm.spawn({ shell, rows: process.stdout.rows, cols: process.stdout.columns });
|
|
15
|
+
export const render = async (shell, underTest) => {
|
|
16
|
+
const term = await isterm.spawn({ shell, rows: process.stdout.rows, cols: process.stdout.columns, underTest });
|
|
16
17
|
const suggestionManager = new SuggestionManager(term, shell);
|
|
17
18
|
let hasActiveSuggestions = false;
|
|
18
19
|
let previousSuggestionsRows = 0;
|
|
19
|
-
process.stdin.
|
|
20
|
+
if (process.stdin.isTTY)
|
|
21
|
+
process.stdin.setRawMode(true);
|
|
22
|
+
readline.emitKeypressEvents(process.stdin);
|
|
20
23
|
const writeOutput = (data) => {
|
|
21
24
|
log.debug({ msg: "writing data", data });
|
|
22
25
|
process.stdout.write(data);
|
|
@@ -27,7 +30,7 @@ export const render = async (shell) => {
|
|
|
27
30
|
// Considers when data includes newlines which have shifted the cursor position downwards
|
|
28
31
|
const newlines = Math.max((data.match(/\r/g) || []).length, (data.match(/\n/g) || []).length);
|
|
29
32
|
const linesOfInterest = MAX_LINES + newlines;
|
|
30
|
-
if (term.getCursorState().remainingLines <=
|
|
33
|
+
if (term.getCursorState().remainingLines <= MAX_LINES) {
|
|
31
34
|
// handles when suggestions get loaded before shell output so you need to always clear below output as a precaution
|
|
32
35
|
if (term.getCursorState().remainingLines != 0) {
|
|
33
36
|
writeOutput(ansi.cursorHide + ansi.cursorSavePosition + eraseLinesBelow(linesOfInterest + 1) + ansi.cursorRestorePosition);
|
|
@@ -47,12 +50,13 @@ export const render = async (shell) => {
|
|
|
47
50
|
else {
|
|
48
51
|
writeOutput(data);
|
|
49
52
|
}
|
|
50
|
-
|
|
51
|
-
|
|
53
|
+
process.nextTick(async () => {
|
|
54
|
+
// validate result to prevent stale suggestion being provided
|
|
55
|
+
const suggestion = suggestionManager.validate(await suggestionManager.render(term.getCursorState().remainingLines));
|
|
52
56
|
const commandState = term.getCommandState();
|
|
53
57
|
if (suggestion.data != "" && commandState.cursorTerminated && !commandState.hasOutput) {
|
|
54
58
|
if (hasActiveSuggestions) {
|
|
55
|
-
if (term.getCursorState().remainingLines <
|
|
59
|
+
if (term.getCursorState().remainingLines < MAX_LINES) {
|
|
56
60
|
writeOutput(ansi.cursorHide +
|
|
57
61
|
ansi.cursorSavePosition +
|
|
58
62
|
ansi.cursorPrevLine.repeat(MAX_LINES) +
|
|
@@ -76,7 +80,7 @@ export const render = async (shell) => {
|
|
|
76
80
|
}
|
|
77
81
|
}
|
|
78
82
|
else {
|
|
79
|
-
if (term.getCursorState().remainingLines <
|
|
83
|
+
if (term.getCursorState().remainingLines < MAX_LINES) {
|
|
80
84
|
writeOutput(ansi.cursorHide + ansi.cursorSavePosition + ansi.cursorUp() + suggestion.data + ansi.cursorRestorePosition + ansi.cursorShow);
|
|
81
85
|
}
|
|
82
86
|
else {
|
|
@@ -92,7 +96,7 @@ export const render = async (shell) => {
|
|
|
92
96
|
}
|
|
93
97
|
else {
|
|
94
98
|
if (hasActiveSuggestions) {
|
|
95
|
-
if (term.getCursorState().remainingLines <=
|
|
99
|
+
if (term.getCursorState().remainingLines <= MAX_LINES) {
|
|
96
100
|
writeOutput(ansi.cursorHide +
|
|
97
101
|
ansi.cursorSavePosition +
|
|
98
102
|
ansi.cursorPrevLine.repeat(MAX_LINES) +
|
|
@@ -109,13 +113,19 @@ export const render = async (shell) => {
|
|
|
109
113
|
previousSuggestionsRows = suggestion.rows;
|
|
110
114
|
});
|
|
111
115
|
});
|
|
112
|
-
process.stdin.on("
|
|
113
|
-
const
|
|
114
|
-
|
|
116
|
+
process.stdin.on("keypress", (...keyPress) => {
|
|
117
|
+
const press = keyPress[1];
|
|
118
|
+
const inputHandled = suggestionManager.update(press);
|
|
119
|
+
if (previousSuggestionsRows > 0 && inputHandled) {
|
|
115
120
|
term.noop();
|
|
116
121
|
}
|
|
117
|
-
else if (
|
|
118
|
-
|
|
122
|
+
else if (!inputHandled) {
|
|
123
|
+
if (press.name == "backspace" && (shell === Shell.Pwsh || shell === Shell.Powershell || shell === Shell.Cmd)) {
|
|
124
|
+
term.write("\u007F");
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
term.write(press.sequence);
|
|
128
|
+
}
|
|
119
129
|
}
|
|
120
130
|
});
|
|
121
131
|
term.onExit(({ exitCode }) => {
|
package/build/utils/ansi.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
|
2
2
|
// Licensed under the MIT License.
|
|
3
3
|
const ESC = "\u001B";
|
|
4
|
-
const CSI = "
|
|
4
|
+
const CSI = ESC + "[";
|
|
5
5
|
const OSC = "\u001B]";
|
|
6
6
|
const BEL = "\u0007";
|
|
7
|
-
const SS3 = "\u001BO";
|
|
8
7
|
export const IsTermOscPs = 6973;
|
|
9
8
|
const IS_OSC = OSC + IsTermOscPs + ";";
|
|
10
9
|
export var IstermOscPt;
|
|
@@ -32,25 +31,3 @@ export const scrollDown = (count = 1) => CSI + count + "T";
|
|
|
32
31
|
export const eraseLinesBelow = (count = 1) => {
|
|
33
32
|
return [...Array(count).keys()].map(() => cursorNextLine + eraseLine).join("");
|
|
34
33
|
};
|
|
35
|
-
export const parseKeystroke = (b) => {
|
|
36
|
-
let s;
|
|
37
|
-
if (b[0] > 127 && b[1] === undefined) {
|
|
38
|
-
b[0] -= 128;
|
|
39
|
-
s = "\u001B" + String(b);
|
|
40
|
-
}
|
|
41
|
-
else {
|
|
42
|
-
s = String(b);
|
|
43
|
-
}
|
|
44
|
-
if (s == ESC) {
|
|
45
|
-
return "esc";
|
|
46
|
-
}
|
|
47
|
-
else if (s == CSI + "A" || s == SS3 + "A") {
|
|
48
|
-
return "up";
|
|
49
|
-
}
|
|
50
|
-
else if (s == CSI + "B" || s == SS3 + "B") {
|
|
51
|
-
return "down";
|
|
52
|
-
}
|
|
53
|
-
else if (s == "\t") {
|
|
54
|
-
return "tab";
|
|
55
|
-
}
|
|
56
|
-
};
|
package/package.json
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@microsoft/inshellisense",
|
|
3
|
-
"version": "0.0.1-rc.
|
|
3
|
+
"version": "0.0.1-rc.8",
|
|
4
4
|
"description": "IDE style command line auto complete",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=16.6.0 <21.0.0"
|
|
8
|
+
},
|
|
6
9
|
"bin": {
|
|
7
10
|
"inshellisense": "./build/index.js",
|
|
8
11
|
"is": "./build/index.js"
|
|
@@ -15,11 +18,13 @@
|
|
|
15
18
|
],
|
|
16
19
|
"scripts": {
|
|
17
20
|
"build": "tsc",
|
|
18
|
-
"
|
|
21
|
+
"dev": "node --loader ts-node/esm src/index.ts -V",
|
|
19
22
|
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
|
|
23
|
+
"test:e2e": "tui-test",
|
|
20
24
|
"lint": "eslint src/ --ext .ts,.tsx && prettier src/ --check",
|
|
21
25
|
"lint:fix": "eslint src/ --ext .ts,.tsx --fix && prettier src/ --write",
|
|
22
|
-
"debug": "node --inspect --loader ts-node/esm src/index.ts -V"
|
|
26
|
+
"debug": "node --inspect --loader ts-node/esm src/index.ts -V",
|
|
27
|
+
"pre-commit": "lint-staged"
|
|
23
28
|
},
|
|
24
29
|
"repository": {
|
|
25
30
|
"type": "git",
|
|
@@ -34,14 +39,15 @@
|
|
|
34
39
|
},
|
|
35
40
|
"homepage": "https://github.com/microsoft/inshellisense#readme",
|
|
36
41
|
"dependencies": {
|
|
37
|
-
"@
|
|
42
|
+
"@homebridge/node-pty-prebuilt-multiarch": "^0.11.12",
|
|
43
|
+
"@microsoft/tui-test": "^0.0.1-rc.3",
|
|
44
|
+
"@withfig/autocomplete": "2.651.0",
|
|
38
45
|
"ajv": "^8.12.0",
|
|
39
46
|
"ansi-escapes": "^6.2.0",
|
|
40
47
|
"ansi-styles": "^6.2.1",
|
|
41
48
|
"chalk": "^5.3.0",
|
|
42
49
|
"commander": "^11.0.0",
|
|
43
50
|
"find-process": "^1.4.7",
|
|
44
|
-
"node-pty": "^1.0.0",
|
|
45
51
|
"which": "^4.0.0",
|
|
46
52
|
"wrap-ansi": "^8.1.0",
|
|
47
53
|
"xterm-headless": "^5.3.0"
|
|
@@ -58,10 +64,18 @@
|
|
|
58
64
|
"eslint-config-prettier": "^9.0.0",
|
|
59
65
|
"eslint-plugin-header": "^3.1.1",
|
|
60
66
|
"eslint-plugin-react": "^7.33.2",
|
|
67
|
+
"husky": "^9.0.11",
|
|
61
68
|
"jest": "^29.7.0",
|
|
69
|
+
"lint-staged": "^15.2.2",
|
|
62
70
|
"prettier": "3.0.3",
|
|
63
71
|
"ts-jest": "^29.1.1",
|
|
64
72
|
"ts-node": "^10.9.2",
|
|
65
73
|
"typescript": "^5.2.2"
|
|
74
|
+
},
|
|
75
|
+
"lint-staged": {
|
|
76
|
+
"{,src/**/}*.{ts,tsx}": [
|
|
77
|
+
"eslint --fix",
|
|
78
|
+
"prettier --write"
|
|
79
|
+
]
|
|
66
80
|
}
|
|
67
81
|
}
|
|
@@ -36,15 +36,21 @@ __is_escape_value() {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
__is_update_cwd() {
|
|
39
|
-
builtin printf '\e]6973;CWD;%s\a' "$(
|
|
39
|
+
builtin printf '\e]6973;CWD;%s\a' "$(__is_escape_value "${PWD}")"
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
__is_update_prompt() {
|
|
43
43
|
__is_prior_prompt="$PS1"
|
|
44
|
-
|
|
44
|
+
if [[ $ISTERM_TESTING == "1" ]]; then
|
|
45
|
+
__is_prior_prompt="> "
|
|
46
|
+
fi
|
|
47
|
+
PS1="%{$(__is_prompt_start)%}$__is_prior_prompt%{$(__is_prompt_end)%}"
|
|
45
48
|
}
|
|
46
49
|
|
|
47
50
|
__is_precmd() {
|
|
51
|
+
if [[ $PS1 != *"$(__is_prompt_start)"* ]]; then
|
|
52
|
+
__is_update_prompt
|
|
53
|
+
fi
|
|
48
54
|
__is_update_cwd
|
|
49
55
|
}
|
|
50
56
|
|
|
@@ -57,6 +57,9 @@ fi
|
|
|
57
57
|
__is_update_prompt() {
|
|
58
58
|
if [[ "$__is_custom_PS1" == "" || "$__is_custom_PS1" != "$PS1" ]]; then
|
|
59
59
|
__is_original_PS1=$PS1
|
|
60
|
+
if [ $ISTERM_TESTING == "1" ]; then
|
|
61
|
+
__is_original_PS1="> "
|
|
62
|
+
fi
|
|
60
63
|
__is_custom_PS1="\[$(__is_prompt_start)\]$__is_original_PS1\[$(__is_prompt_end)\]"
|
|
61
64
|
export PS1="$__is_custom_PS1"
|
|
62
65
|
fi
|
|
@@ -11,4 +11,9 @@ end
|
|
|
11
11
|
function __is_update_cwd --on-event fish_prompt; set __is_cwd (__is_escape_value "$PWD"); printf "\e]6973;CWD;$__is_cwd\a"; end
|
|
12
12
|
|
|
13
13
|
__is_copy_function fish_prompt is_user_prompt
|
|
14
|
+
|
|
15
|
+
if [ "$ISTERM_TESTING" = "1" ]
|
|
16
|
+
function is_user_prompt; printf '> '; end
|
|
17
|
+
end
|
|
18
|
+
|
|
14
19
|
function fish_prompt; printf (__is_prompt_start); printf (is_user_prompt); printf (__is_prompt_end); end
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
$Global:__IsOriginalPrompt = $function:Prompt
|
|
2
2
|
|
|
3
|
+
function Global:__IsTestingPrompt() {
|
|
4
|
+
return "PS > "
|
|
5
|
+
}
|
|
6
|
+
if ($env:ISTERM_TESTING -eq "1") {
|
|
7
|
+
$Global:__IsOriginalPrompt = $function:__IsTestingPrompt
|
|
8
|
+
}
|
|
9
|
+
|
|
3
10
|
function Global:__IS-Escape-Value([string]$value) {
|
|
4
11
|
[regex]::Replace($value, '[\\\n;]', { param($match)
|
|
5
12
|
-Join (
|