mirror of
https://github.com/binaricat/Netcatty.git
synced 2026-10-09 15:58:34 +00:00
f4aa6ddb46
Inline (ghost-text) suggestions render suggestion.substring(trackedInput.length) after the cursor, where trackedInput is a client-side reconstruction of the command line (buffer heuristics + keystroke prediction, to mask SSH echo latency). On hosts with non-standard echo — hardware bastion hosts / network OS like `ecOS#` (#1013, previously #756 / #906) — that reconstruction drifts and the ghost gets painted over characters the user already typed (`int` + ghost `terface` -> `intterface`). Add a fail-safe consistency check: on each post-echo render, if the real terminal line before the cursor contains the tracked input followed by more untracked, non-whitespace characters (reality is AHEAD of what we tracked), hide the ghost instead of drawing it over real text. SSH echo latency is the opposite case (the line is a prefix-behind of the tracked input) and is deliberately not flagged, so the ghost stays responsive on slow links. The check is ASCII-only (wide-char column mapping is ambiguous) and fail-open, so it can only ever suppress a ghost that would otherwise corrupt — never change correct behaviour. This converts the recurring "ghost shows already-typed characters" bug into "ghost simply doesn't show" on devices we can't track reliably. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
46 lines
1.9 KiB
TypeScript
46 lines
1.9 KiB
TypeScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
import { lineHasUntrackedTrailingInput } from "./autocomplete/ghostTextConsistency.ts";
|
|
|
|
test("keeps the ghost when the line matches the tracked input (in sync)", () => {
|
|
assert.equal(lineHasUntrackedTrailingInput("network int", "ecOS# network int"), false);
|
|
});
|
|
|
|
test("hides the ghost when the device echoed untracked trailing input (#1013)", () => {
|
|
// Tracked is one char behind what the device actually shows.
|
|
assert.equal(lineHasUntrackedTrailingInput("network in", "ecOS# network int"), true);
|
|
});
|
|
|
|
test("keeps the ghost during echo latency (line is behind the tracked input)", () => {
|
|
// The tracked input hasn't been fully echoed yet — reality being behind
|
|
// never corrupts, so the ghost must stay.
|
|
assert.equal(lineHasUntrackedTrailingInput("network int", "ecOS# network in"), false);
|
|
});
|
|
|
|
test("ignores trailing whitespace after the tracked input", () => {
|
|
assert.equal(lineHasUntrackedTrailingInput("git", "$ git "), false);
|
|
});
|
|
|
|
test("hides when untracked non-space input follows the tracked input", () => {
|
|
assert.equal(lineHasUntrackedTrailingInput("git", "$ git push"), true);
|
|
});
|
|
|
|
test("uses the last occurrence so a repeated token earlier on the line is ignored", () => {
|
|
// Prompt contains 'int'; the real typed 'int' is the one at the end.
|
|
assert.equal(lineHasUntrackedTrailingInput("int", "user@int-host:~$ int"), false);
|
|
assert.equal(lineHasUntrackedTrailingInput("int", "user@int-host:~$ intf"), true);
|
|
});
|
|
|
|
test("skips non-ASCII input (wide-char column mapping is ambiguous)", () => {
|
|
assert.equal(lineHasUntrackedTrailingInput("网络", "$ 网络口"), false);
|
|
});
|
|
|
|
test("skips single-character input", () => {
|
|
assert.equal(lineHasUntrackedTrailingInput("l", "$ lx"), false);
|
|
});
|
|
|
|
test("returns false when the tracked input isn't on the line yet (latency)", () => {
|
|
assert.equal(lineHasUntrackedTrailingInput("systemctl", "$ sys"), false);
|
|
});
|