未验证 提交 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 {
this._baseY = buffer.baseY;
}
public getLine() {
return this.buffer.getLine(this._y + this._baseY);
}
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) {
......@@ -403,17 +407,22 @@ class BackspacePrediction implements IPrediction {
pos: ICoordinate;
oldAttributes: string;
oldChar: string;
eol: boolean;
};
constructor(private readonly terminal: Terminal) { }
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();
this.appliedAt = cell
? { pos: cursor.coordinate, oldAttributes: attributesToSeq(cell), oldChar: cell.getChars() }
: { pos: cursor.coordinate, oldAttributes: '', oldChar: '' };
? { eol, pos: cursor.coordinate, oldAttributes: attributesToSeq(cell), oldChar: cell.getChars() }
: { eol, pos: cursor.coordinate, oldAttributes: '', oldChar: '' };
return cursor.shift(-1) + DELETE_CHAR;
return move + DELETE_CHAR;
}
public rollback(cursor: Cursor) {
......@@ -434,8 +443,7 @@ class BackspacePrediction implements IPrediction {
}
public matches(input: StringReader) {
const isEOL = this.appliedAt?.oldChar === '';
if (isEOL) {
if (this.appliedAt?.eol) {
const r1 = input.eatGradually(`\b${CSI}K`);
if (r1 !== MatchResult.Failure) {
return r1;
......
......@@ -213,6 +213,16 @@ suite('Workbench - Terminal Typeahead', () => {
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', () => {
const t = createMockTerminal({ lines: ['hello|'] });
addon.activate(t.terminal);
......@@ -332,6 +342,10 @@ function createMockTerminal({ lines, cursorAttrs }: {
return {
length: s.length,
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.
先完成此消息的编辑!
想要评论请 注册