mirror of
https://github.com/wavetermdev/inshellisense.git
synced 2026-08-05 13:43:30 -07:00
fix: batched keypress events failed to be recognized. (#167)
* fix: use 'keypress' event instead of 'data' and use readline's built in parsing to support batched key actions Signed-off-by: Chapman Pendery <cpendery@vt.edu> * fix: drop coming pr code Signed-off-by: Chapman Pendery <cpendery@vt.edu> --------- Signed-off-by: Chapman Pendery <cpendery@vt.edu>
This commit is contained in:
@@ -1,10 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
export const inputModifier = (input: Buffer): string => {
|
||||
switch (input.toString()) {
|
||||
case "\b":
|
||||
return "\u007F"; // DEL
|
||||
}
|
||||
return input.toString();
|
||||
};
|
||||
@@ -7,8 +7,8 @@ import { ISTerm } from "../isterm/pty.js";
|
||||
import { renderBox, truncateText, truncateMultilineText } from "./utils.js";
|
||||
import ansi from "ansi-escapes";
|
||||
import chalk from "chalk";
|
||||
import { parseKeystroke } from "../utils/ansi.js";
|
||||
import { Shell } from "../utils/shell.js";
|
||||
import log from "../utils/log.js";
|
||||
|
||||
const maxSuggestions = 5;
|
||||
const suggestionWidth = 40;
|
||||
@@ -22,6 +22,13 @@ type SuggestionsSequence = {
|
||||
rows: number;
|
||||
};
|
||||
|
||||
export type KeyPressEvent = [string | null | undefined, KeyPress];
|
||||
|
||||
type KeyPress = {
|
||||
sequence: string;
|
||||
name: string;
|
||||
};
|
||||
|
||||
export class SuggestionManager {
|
||||
#term: ISTerm;
|
||||
#command: string;
|
||||
@@ -140,16 +147,15 @@ export class SuggestionManager {
|
||||
};
|
||||
}
|
||||
|
||||
update(input: Buffer): "handled" | "fully-handled" | false {
|
||||
const keyStroke = parseKeystroke(input);
|
||||
if (keyStroke == null) return false;
|
||||
if (keyStroke == "esc") {
|
||||
update(keyPress: KeyPress): boolean {
|
||||
const { name } = keyPress;
|
||||
if (name == "escape") {
|
||||
this.#suggestBlob = undefined;
|
||||
} else if (keyStroke == "up") {
|
||||
} else if (name == "up") {
|
||||
this.#activeSuggestionIdx = Math.max(0, this.#activeSuggestionIdx - 1);
|
||||
} else if (keyStroke == "down") {
|
||||
} else if (name == "down") {
|
||||
this.#activeSuggestionIdx = Math.min(this.#activeSuggestionIdx + 1, (this.#suggestBlob?.suggestions.length ?? 1) - 1);
|
||||
} else if (keyStroke == "tab") {
|
||||
} else if (name == "tab") {
|
||||
const removals = "\u007F".repeat(this.#suggestBlob?.charactersToDrop ?? 0);
|
||||
const suggestion = this.#suggestBlob?.suggestions.at(this.#activeSuggestionIdx);
|
||||
const chars = suggestion?.insertValue ?? suggestion?.name + " ";
|
||||
@@ -157,7 +163,10 @@ export class SuggestionManager {
|
||||
return false;
|
||||
}
|
||||
this.#term.write(removals + chars);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return "handled";
|
||||
log.debug({ msg: "handled keypress", ...keyPress });
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+11
-8
@@ -1,15 +1,15 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import readline from "node:readline";
|
||||
import ansi from "ansi-escapes";
|
||||
import chalk from "chalk";
|
||||
|
||||
import { inputModifier } from "./input.js";
|
||||
import log from "../utils/log.js";
|
||||
import { Shell } from "../utils/shell.js";
|
||||
import isterm from "../isterm/index.js";
|
||||
import { eraseLinesBelow } from "../utils/ansi.js";
|
||||
import { SuggestionManager, MAX_LINES } from "./suggestionManager.js";
|
||||
import { SuggestionManager, MAX_LINES, KeyPressEvent } from "./suggestionManager.js";
|
||||
|
||||
export const renderConfirmation = (live: boolean): string => {
|
||||
const statusMessage = live ? chalk.green("live") : chalk.red("not found");
|
||||
@@ -21,7 +21,8 @@ export const render = async (shell: Shell) => {
|
||||
const suggestionManager = new SuggestionManager(term, shell);
|
||||
let hasActiveSuggestions = false;
|
||||
let previousSuggestionsRows = 0;
|
||||
process.stdin.setRawMode(true);
|
||||
if (process.stdin.isTTY) process.stdin.setRawMode(true);
|
||||
readline.emitKeypressEvents(process.stdin);
|
||||
|
||||
const writeOutput = (data: string) => {
|
||||
log.debug({ msg: "writing data", data });
|
||||
@@ -122,12 +123,14 @@ export const render = async (shell: Shell) => {
|
||||
previousSuggestionsRows = suggestion.rows;
|
||||
});
|
||||
});
|
||||
process.stdin.on("data", (d: Buffer) => {
|
||||
const suggestionResult = suggestionManager.update(d);
|
||||
if (previousSuggestionsRows > 0 && suggestionResult == "handled") {
|
||||
|
||||
process.stdin.on("keypress", (...keyPress: KeyPressEvent) => {
|
||||
const press = keyPress[1];
|
||||
const inputHandled = suggestionManager.update(press);
|
||||
if (previousSuggestionsRows > 0 && inputHandled) {
|
||||
term.noop();
|
||||
} else if (suggestionResult != "fully-handled") {
|
||||
term.write(inputModifier(d));
|
||||
} else if (!inputHandled) {
|
||||
term.write(press.sequence);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
+1
-22
@@ -2,10 +2,9 @@
|
||||
// Licensed under the MIT License.
|
||||
|
||||
const ESC = "\u001B";
|
||||
const CSI = "\u001B[";
|
||||
const CSI = ESC + "[";
|
||||
const OSC = "\u001B]";
|
||||
const BEL = "\u0007";
|
||||
const SS3 = "\u001BO";
|
||||
|
||||
export const IsTermOscPs = 6973;
|
||||
const IS_OSC = OSC + IsTermOscPs + ";";
|
||||
@@ -35,23 +34,3 @@ export const scrollDown = (count = 1) => CSI + count + "T";
|
||||
export const eraseLinesBelow = (count = 1) => {
|
||||
return [...Array(count).keys()].map(() => cursorNextLine + eraseLine).join("");
|
||||
};
|
||||
|
||||
export const parseKeystroke = (b: Buffer): "up" | "down" | "tab" | "esc" | undefined => {
|
||||
let s: string;
|
||||
if (b[0] > 127 && b[1] === undefined) {
|
||||
b[0] -= 128;
|
||||
s = "\u001B" + String(b);
|
||||
} else {
|
||||
s = String(b);
|
||||
}
|
||||
|
||||
if (s == ESC) {
|
||||
return "esc";
|
||||
} else if (s == CSI + "A" || s == SS3 + "A") {
|
||||
return "up";
|
||||
} else if (s == CSI + "B" || s == SS3 + "B") {
|
||||
return "down";
|
||||
} else if (s == "\t") {
|
||||
return "tab";
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user