Skip to content

Commit a11ba0a

Browse files
authored
Merge pull request #3365 from jerch/fix_3362
allow cursor to stick at cols in ED/EL
2 parents e2ed603 + 2134e05 commit a11ba0a

File tree

3 files changed

+89
-2
lines changed

3 files changed

+89
-2
lines changed

src/browser/Terminal2.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const ROWS = 25;
1717

1818
const TESTFILES = glob.sync('**/escape_sequence_files/*.in', { cwd: path.join(__dirname, '../..')});
1919
const SKIP_FILES = [
20+
't0055-EL.in', // EL/ED handle cursor at cols differently (see #3362)
2021
't0084-CBT.in',
2122
't0101-NLM.in',
2223
't0103-reverse_wrap.in', // not comparable, we deviate from xterm reverse wrap on purpose

src/common/InputHandler.test.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1913,6 +1913,92 @@ describe('InputHandler', () => {
19131913
});
19141914
});
19151915
});
1916+
1917+
// issue #3362 and #2979
1918+
describe('EL/ED cursor at buffer.cols', () => {
1919+
beforeEach(() => {
1920+
bufferService.resize(10, 5);
1921+
});
1922+
describe('cursor should stay at cols / does not overflow', () => {
1923+
it('EL0', async () => {
1924+
await inputHandler.parseP('##########\x1b[0K');
1925+
assert.equal(bufferService.buffer.x, 10);
1926+
assert.deepEqual(getLines(bufferService), ['#'.repeat(10), '', '', '', '']);
1927+
});
1928+
it('EL1', async () => {
1929+
await inputHandler.parseP('##########\x1b[1K');
1930+
assert.equal(bufferService.buffer.x, 10);
1931+
assert.deepEqual(getLines(bufferService), ['', '', '', '', '']);
1932+
});
1933+
it('EL2', async () => {
1934+
await inputHandler.parseP('##########\x1b[2K');
1935+
assert.equal(bufferService.buffer.x, 10);
1936+
assert.deepEqual(getLines(bufferService), ['', '', '', '', '']);
1937+
});
1938+
it('ED0', async () => {
1939+
await inputHandler.parseP('##########\x1b[0J');
1940+
assert.equal(bufferService.buffer.x, 10);
1941+
assert.deepEqual(getLines(bufferService), ['#'.repeat(10), '', '', '', '']);
1942+
});
1943+
it('ED1', async () => {
1944+
await inputHandler.parseP('##########\x1b[1J');
1945+
assert.equal(bufferService.buffer.x, 10);
1946+
assert.deepEqual(getLines(bufferService), ['', '', '', '', '']);
1947+
});
1948+
it('ED2', async () => {
1949+
await inputHandler.parseP('##########\x1b[2J');
1950+
assert.equal(bufferService.buffer.x, 10);
1951+
assert.deepEqual(getLines(bufferService), ['', '', '', '', '']);
1952+
});
1953+
it('ED3', async () => {
1954+
await inputHandler.parseP('##########\x1b[3J');
1955+
assert.equal(bufferService.buffer.x, 10);
1956+
assert.deepEqual(getLines(bufferService), ['#'.repeat(10), '', '', '', '']);
1957+
});
1958+
});
1959+
describe('following sequence keeps working', () => {
1960+
// sequences to test (cursor related ones)
1961+
const SEQ = [
1962+
/* ICH */ '\x1b[10@',
1963+
/* SL */ '\x1b[10 @',
1964+
/* CUU */ '\x1b[10A',
1965+
/* SR */ '\x1b[10 A',
1966+
/* CUD */ '\x1b[10B',
1967+
/* CUF */ '\x1b[10C',
1968+
/* CUB */ '\x1b[10D',
1969+
/* CNL */ '\x1b[10E',
1970+
/* CPL */ '\x1b[10F',
1971+
/* CHA */ '\x1b[10G',
1972+
/* CUP */ '\x1b[10;10H',
1973+
/* CHT */ '\x1b[10I',
1974+
/* IL */ '\x1b[10L',
1975+
/* DL */ '\x1b[10M',
1976+
/* DCH */ '\x1b[10P',
1977+
/* SU */ '\x1b[10S',
1978+
/* SD */ '\x1b[10T',
1979+
/* ECH */ '\x1b[10X',
1980+
/* CBT */ '\x1b[10Z',
1981+
/* HPA */ '\x1b[10`',
1982+
/* HPR */ '\x1b[10a',
1983+
/* REP */ '\x1b[10b',
1984+
/* VPA */ '\x1b[10d',
1985+
/* VPR */ '\x1b[10e',
1986+
/* HVP */ '\x1b[10;10f',
1987+
/* TBC */ '\x1b[0g',
1988+
/* SCOSC */ '\x1b[s',
1989+
/* DECIC */ '\x1b[10\'}',
1990+
/* DECDC */ '\x1b[10\'~'
1991+
];
1992+
it('cursor never advances beyond cols', async () => {
1993+
for (const seq of SEQ) {
1994+
await inputHandler.parseP('##########\x1b[2J' + seq);
1995+
assert.equal(bufferService.buffer.x <= bufferService.cols, true);
1996+
inputHandler.reset();
1997+
bufferService.reset();
1998+
}
1999+
});
2000+
});
2001+
});
19162002
});
19172003

19182004

src/common/InputHandler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,7 +1247,7 @@ export class InputHandler extends Disposable implements IInputHandler {
12471247
* @vt: #P[Protection attributes are not supported.] CSI DECSED "Selective Erase In Display" "CSI ? Ps J" "Currently the same as ED."
12481248
*/
12491249
public eraseInDisplay(params: IParams): boolean {
1250-
this._restrictCursor();
1250+
this._restrictCursor(this._bufferService.cols);
12511251
let j;
12521252
switch (params.params[0]) {
12531253
case 0:
@@ -1319,7 +1319,7 @@ export class InputHandler extends Disposable implements IInputHandler {
13191319
* @vt: #P[Protection attributes are not supported.] CSI DECSEL "Selective Erase In Line" "CSI ? Ps K" "Currently the same as EL."
13201320
*/
13211321
public eraseInLine(params: IParams): boolean {
1322-
this._restrictCursor();
1322+
this._restrictCursor(this._bufferService.cols);
13231323
switch (params.params[0]) {
13241324
case 0:
13251325
this._eraseInBufferLine(this._bufferService.buffer.y, this._bufferService.buffer.x, this._bufferService.cols);

0 commit comments

Comments
 (0)