未验证 提交 fd9ace84 编写于 作者: C Connor Peet

terminal: fix typeahead leaving stray characters with backspaces

Fixes https://github.com/microsoft/vscode/issues/109704
Fixes https://github.com/microsoft/vscode-internalbacklog/issues/1575
上级 cbb21a30
...@@ -79,8 +79,12 @@ class Cursor implements ICoordinate { ...@@ -79,8 +79,12 @@ class Cursor implements ICoordinate {
this._baseY = buffer.baseY; this._baseY = buffer.baseY;
} }
public getLine() {
return this.buffer.getLine(this._y + this._baseY);
}
public getCell(loadInto?: IBufferCell) { public getCell(loadInto?: IBufferCell) {
return this.buffer.getLine(this._y + this._baseY)?.getCell(this._x, loadInto); return this.getLine()?.getCell(this._x, loadInto);
} }
public moveTo(coordinate: ICoordinate) { public moveTo(coordinate: ICoordinate) {
...@@ -403,17 +407,22 @@ class BackspacePrediction implements IPrediction { ...@@ -403,17 +407,22 @@ class BackspacePrediction implements IPrediction {
pos: ICoordinate; pos: ICoordinate;
oldAttributes: string; oldAttributes: string;
oldChar: string; oldChar: string;
eol: boolean;
}; };
constructor(private readonly terminal: Terminal) { } constructor(private readonly terminal: Terminal) { }
public apply(_: IBuffer, cursor: Cursor) { public apply(_: IBuffer, cursor: Cursor) {
// at eol if everything to the right is whitespace (zsh will emit a "clear line" code in this case)
// todo: can be optimized if `getTrimmedLength` is exposed from xterm
const eol = !cursor.getLine()?.translateToString(true, cursor.x);
const move = cursor.shift(-1);
const cell = cursor.getCell(); const cell = cursor.getCell();
this.appliedAt = cell this.appliedAt = cell
? { pos: cursor.coordinate, oldAttributes: attributesToSeq(cell), oldChar: cell.getChars() } ? { eol, pos: cursor.coordinate, oldAttributes: attributesToSeq(cell), oldChar: cell.getChars() }
: { pos: cursor.coordinate, oldAttributes: '', oldChar: '' }; : { eol, pos: cursor.coordinate, oldAttributes: '', oldChar: '' };
return cursor.shift(-1) + DELETE_CHAR; return move + DELETE_CHAR;
} }
public rollback(cursor: Cursor) { public rollback(cursor: Cursor) {
...@@ -434,8 +443,7 @@ class BackspacePrediction implements IPrediction { ...@@ -434,8 +443,7 @@ class BackspacePrediction implements IPrediction {
} }
public matches(input: StringReader) { public matches(input: StringReader) {
const isEOL = this.appliedAt?.oldChar === ''; if (this.appliedAt?.eol) {
if (isEOL) {
const r1 = input.eatGradually(`\b${CSI}K`); const r1 = input.eatGradually(`\b${CSI}K`);
if (r1 !== MatchResult.Failure) { if (r1 !== MatchResult.Failure) {
return r1; return r1;
......
...@@ -213,6 +213,16 @@ suite('Workbench - Terminal Typeahead', () => { ...@@ -213,6 +213,16 @@ suite('Workbench - Terminal Typeahead', () => {
assert.strictEqual(addon.stats?.accuracy, 1); assert.strictEqual(addon.stats?.accuracy, 1);
}); });
test('restores old character after invalid backspace', () => {
const t = createMockTerminal({ lines: ['hel|lo'] });
addon.activate(t.terminal);
(addon as any).lastRow = { y: 1, startingX: 1 };
t.onData('\x7F');
t.expectWritten(`${CSI}2;4H${CSI}X`);
expectProcessed('x', `${CSI}?25l${CSI}0ml${CSI}2;4H${CSI}0mx${CSI}?25h`);
assert.strictEqual(addon.stats?.accuracy, 0);
});
test('waits for validation before deleting to left of cursor', () => { test('waits for validation before deleting to left of cursor', () => {
const t = createMockTerminal({ lines: ['hello|'] }); const t = createMockTerminal({ lines: ['hello|'] });
addon.activate(t.terminal); addon.activate(t.terminal);
...@@ -332,6 +342,10 @@ function createMockTerminal({ lines, cursorAttrs }: { ...@@ -332,6 +342,10 @@ function createMockTerminal({ lines, cursorAttrs }: {
return { return {
length: s.length, length: s.length,
getCell: (x: number) => mockCell(s[x - 1] || ''), getCell: (x: number) => mockCell(s[x - 1] || ''),
translateToString: (trim: boolean, start = 0, end = s.length) => {
const out = s.slice(start, end);
return trim ? out.trimRight() : out;
},
}; };
}, },
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册