Merge branch 'master' into strikethrough

This commit is contained in:
Daniel Imms
2021-07-09 06:53:05 -07:00
committed by GitHub
36 changed files with 179 additions and 96 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ export function clone<T>(val: T, depth: number = 5): T {
for (const key in val) {
// Recursively clone eack item unless we're at the maximum depth
clonedObject[key] = depth <= 1 ? val[key] : (val[key] ? clone(val[key], depth - 1) : val[key]);
clonedObject[key] = depth <= 1 ? val[key] : (val[key] && clone(val[key], depth - 1));
}
return clonedObject as T;
+4
View File
@@ -125,6 +125,10 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
this._onScroll.fire({ position: this._bufferService.buffer.ydisp, source: ScrollSource.TERMINAL });
this._dirtyRowService.markRangeDirty(this._bufferService.buffer.scrollTop, this._bufferService.buffer.scrollBottom);
}));
this.register(this._inputHandler.onScroll(event => {
this._onScroll.fire({ position: this._bufferService.buffer.ydisp, source: ScrollSource.TERMINAL });
this._dirtyRowService.markRangeDirty(this._bufferService.buffer.scrollTop, this._bufferService.buffer.scrollBottom);
}));
// Setup WriteBuffer
this._writeBuffer = new WriteBuffer((data, promiseResult) => this._inputHandler.parse(data, promiseResult));
+91 -5
View File
@@ -77,7 +77,7 @@ describe('InputHandler', () => {
optionsService.options.scrollback = 1;
bufferService.reset();
});
it('SL (scrollLeft)', async () => {
it('SL (scrollLeft)', () => {
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[ @');
assert.deepEqual(getLines(bufferService, 6), ['12345', '2345', '2345', '2345', '2345', '2345']);
@@ -86,7 +86,7 @@ describe('InputHandler', () => {
inputHandler.parseP('\x1b[2 @');
assert.deepEqual(getLines(bufferService, 6), ['12345', '5', '5', '5', '5', '5']);
});
it('SR (scrollRight)', async () => {
it('SR (scrollRight)', () => {
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[ A');
assert.deepEqual(getLines(bufferService, 6), ['12345', ' 1234', ' 1234', ' 1234', ' 1234', ' 1234']);
@@ -95,7 +95,7 @@ describe('InputHandler', () => {
inputHandler.parseP('\x1b[2 A');
assert.deepEqual(getLines(bufferService, 6), ['12345', ' 1', ' 1', ' 1', ' 1', ' 1']);
});
it('insertColumns (DECIC)', async () => {
it('insertColumns (DECIC)', () => {
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[\'}');
@@ -111,7 +111,7 @@ describe('InputHandler', () => {
inputHandler.parseP('\x1b[2\'}');
assert.deepEqual(getLines(bufferService, 6), ['12345', '12 3', '12 3', '12 3', '12 3', '12 3']);
});
it('deleteColumns (DECDC)', async () => {
it('deleteColumns (DECDC)', () => {
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[\'~');
@@ -137,7 +137,7 @@ describe('InputHandler', () => {
bufferService.reset();
});
describe('reverseWraparound set', () => {
it('should not reverse outside of scroll margins', async () => {
it('should not reverse outside of scroll margins', () => {
// prepare buffer content
inputHandler.parseP('#####abcdefghijklmnopqrstuvwxy');
assert.deepEqual(getLines(bufferService, 6), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', 'uvwxy']);
@@ -1919,6 +1919,92 @@ describe('InputHandler', () => {
});
});
});
// issue #3362 and #2979
describe('EL/ED cursor at buffer.cols', () => {
beforeEach(() => {
bufferService.resize(10, 5);
});
describe('cursor should stay at cols / does not overflow', () => {
it('EL0', async () => {
await inputHandler.parseP('##########\x1b[0K');
assert.equal(bufferService.buffer.x, 10);
assert.deepEqual(getLines(bufferService), ['#'.repeat(10), '', '', '', '']);
});
it('EL1', async () => {
await inputHandler.parseP('##########\x1b[1K');
assert.equal(bufferService.buffer.x, 10);
assert.deepEqual(getLines(bufferService), ['', '', '', '', '']);
});
it('EL2', async () => {
await inputHandler.parseP('##########\x1b[2K');
assert.equal(bufferService.buffer.x, 10);
assert.deepEqual(getLines(bufferService), ['', '', '', '', '']);
});
it('ED0', async () => {
await inputHandler.parseP('##########\x1b[0J');
assert.equal(bufferService.buffer.x, 10);
assert.deepEqual(getLines(bufferService), ['#'.repeat(10), '', '', '', '']);
});
it('ED1', async () => {
await inputHandler.parseP('##########\x1b[1J');
assert.equal(bufferService.buffer.x, 10);
assert.deepEqual(getLines(bufferService), ['', '', '', '', '']);
});
it('ED2', async () => {
await inputHandler.parseP('##########\x1b[2J');
assert.equal(bufferService.buffer.x, 10);
assert.deepEqual(getLines(bufferService), ['', '', '', '', '']);
});
it('ED3', async () => {
await inputHandler.parseP('##########\x1b[3J');
assert.equal(bufferService.buffer.x, 10);
assert.deepEqual(getLines(bufferService), ['#'.repeat(10), '', '', '', '']);
});
});
describe('following sequence keeps working', () => {
// sequences to test (cursor related ones)
const SEQ = [
/* ICH */ '\x1b[10@',
/* SL */ '\x1b[10 @',
/* CUU */ '\x1b[10A',
/* SR */ '\x1b[10 A',
/* CUD */ '\x1b[10B',
/* CUF */ '\x1b[10C',
/* CUB */ '\x1b[10D',
/* CNL */ '\x1b[10E',
/* CPL */ '\x1b[10F',
/* CHA */ '\x1b[10G',
/* CUP */ '\x1b[10;10H',
/* CHT */ '\x1b[10I',
/* IL */ '\x1b[10L',
/* DL */ '\x1b[10M',
/* DCH */ '\x1b[10P',
/* SU */ '\x1b[10S',
/* SD */ '\x1b[10T',
/* ECH */ '\x1b[10X',
/* CBT */ '\x1b[10Z',
/* HPA */ '\x1b[10`',
/* HPR */ '\x1b[10a',
/* REP */ '\x1b[10b',
/* VPA */ '\x1b[10d',
/* VPR */ '\x1b[10e',
/* HVP */ '\x1b[10;10f',
/* TBC */ '\x1b[0g',
/* SCOSC */ '\x1b[s',
/* DECIC */ '\x1b[10\'}',
/* DECDC */ '\x1b[10\'~'
];
it('cursor never advances beyond cols', async () => {
for (const seq of SEQ) {
await inputHandler.parseP('##########\x1b[2J' + seq);
assert.equal(bufferService.buffer.x <= bufferService.cols, true);
inputHandler.reset();
bufferService.reset();
}
});
});
});
});
+2 -2
View File
@@ -1247,7 +1247,7 @@ export class InputHandler extends Disposable implements IInputHandler {
* @vt: #P[Protection attributes are not supported.] CSI DECSED "Selective Erase In Display" "CSI ? Ps J" "Currently the same as ED."
*/
public eraseInDisplay(params: IParams): boolean {
this._restrictCursor();
this._restrictCursor(this._bufferService.cols);
let j;
switch (params.params[0]) {
case 0:
@@ -1319,7 +1319,7 @@ export class InputHandler extends Disposable implements IInputHandler {
* @vt: #P[Protection attributes are not supported.] CSI DECSEL "Selective Erase In Line" "CSI ? Ps K" "Currently the same as EL."
*/
public eraseInLine(params: IParams): boolean {
this._restrictCursor();
this._restrictCursor(this._bufferService.cols);
switch (params.params[0]) {
case 0:
this._eraseInBufferLine(this._bufferService.buffer.y, this._bufferService.buffer.x, this._bufferService.cols);
+1 -1
View File
@@ -125,7 +125,7 @@ export class MockOptionsService implements IOptionsService {
constructor(testOptions?: IPartialTerminalOptions) {
if (testOptions) {
for (const key of Object.keys(testOptions)) {
this.options[key] = (<any>testOptions)[key];
this.options[key] = (testOptions as any)[key];
}
}
}
+2 -2
View File
@@ -16,10 +16,10 @@ describe('BufferRange', () => {
assert.throws(() => getRangeLength(createRange(1, 3, 1, 1), 0));
});
it('should get range multiple lines', () => {
assert.equal(getRangeLength(createRange(1, 1, 4, 5), 5), 23);
assert.equal(getRangeLength(createRange(1, 1, 4, 5), 5), 24);
});
it('should get range for end line right after start line', () => {
assert.equal(getRangeLength(createRange(1, 1, 7, 2), 5), 11);
assert.equal(getRangeLength(createRange(1, 1, 7, 2), 5), 12);
});
});
});
+2 -5
View File
@@ -5,12 +5,9 @@
import { IBufferRange } from 'xterm';
export function getRangeLength(range: IBufferRange, cols: number): number {
if (range.start.y === range.end.y) {
return range.end.x - range.start.x + 1;
}
export function getRangeLength(range: IBufferRange, bufferCols: number): number {
if (range.start.y > range.end.y) {
throw new Error(`Buffer range end (${range.end.x}, ${range.end.y}) cannot be before start (${range.start.x}, ${range.start.y})`);
}
return cols * (range.end.y - range.start.y - 1) + cols - range.start.x + range.end.x;
return bufferCols * (range.end.y - range.start.y) + (range.end.x - range.start.x + 1);
}