move stuff to inputHandler and move scroll to bufferService

This commit is contained in:
meganrogge
2021-04-01 13:16:39 -07:00
parent 759379dfb1
commit e2885f3a38
7 changed files with 1328 additions and 1353 deletions
+178 -6
View File
@@ -18,6 +18,7 @@ import { clone } from 'common/Clone';
import { BufferService } from 'common/services/BufferService';
import { CoreService } from 'common/services/CoreService';
import { OscHandler } from 'common/parser/OscParser';
import { DirtyRowService } from 'common/services/DirtyRowService';
function getCursor(bufferService: IBufferService): number[] {
return [
@@ -66,11 +67,119 @@ describe('InputHandler', () => {
optionsService = new MockOptionsService();
bufferService = new BufferService(optionsService);
bufferService.resize(80, 30);
coreService = new CoreService(() => {}, bufferService, new MockLogService(), optionsService);
coreService = new CoreService(() => { }, bufferService, new MockLogService(), optionsService);
inputHandler = new TestInputHandler(bufferService, new MockCharsetService(), coreService, new MockDirtyRowService(), new MockLogService(), optionsService, new MockCoreMouseService(), new MockUnicodeService());
});
describe('Terminal InputHandler integration', () => {
function getLines(limit: number): string[] {
const res: string[] = [];
for (let i = 0; i < limit; ++i) {
res.push(bufferService.buffers.active.lines.get(i)!.translateToString(true));
}
return res;
}
// This suite cannot live in InputHandler unless Terminal.scroll moved into IBufferService
describe('SL/SR/DECIC/DECDC', () => {
it('SL (scrollLeft)', async () => {
inputHandler.parseP('12345'.repeat(6));
assert.deepEqual(getLines(5), ['12345', '2345', '2345', '2345', '2345', '2345']);
inputHandler.parseP('\x1b[0 @');
assert.deepEqual(getLines(5), ['12345', '345', '345', '345', '345', '345']);
inputHandler.parseP('\x1b[2 @');
assert.deepEqual(getLines(5), ['12345', '5', '5', '5', '5', '5']);
});
it('SR (scrollRight)', async () => {
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[ A');
assert.deepEqual(getLines(5), ['12345', ' 1234', ' 1234', ' 1234', ' 1234', ' 1234']);
inputHandler.parseP('\x1b[0 A');
assert.deepEqual(getLines(5), ['12345', ' 123', ' 123', ' 123', ' 123', ' 123']);
inputHandler.parseP('\x1b[2 A');
assert.deepEqual(getLines(5), ['12345', ' 1', ' 1', ' 1', ' 1', ' 1']);
});
it('insertColumns (DECIC)', async () => {
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[\'}');
assert.deepEqual(getLines(5), ['12345', '12 34', '12 34', '12 34', '12 34', '12 34']);
inputHandler.reset();
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[1\'}');
assert.deepEqual(getLines(5), ['12345', '12 34', '12 34', '12 34', '12 34', '12 34']);
inputHandler.reset();
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[2\'}');
assert.deepEqual(getLines(5), ['12345', '12 3', '12 3', '12 3', '12 3', '12 3']);
});
it('deleteColumns (DECDC)', async () => {
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[\'~');
assert.deepEqual(getLines(5), ['12345', '1245', '1245', '1245', '1245', '1245']);
inputHandler.reset();
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[1\'~');
assert.deepEqual(getLines(5), ['12345', '1245', '1245', '1245', '1245', '1245']);
inputHandler.reset();
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[2\'~');
assert.deepEqual(getLines(5), ['12345', '125', '125', '125', '125', '125']);
});
});
describe('BS with reverseWraparound set/unset', () => {
const ttyBS = '\x08 \x08'; // tty ICANON sends <BS SP BS> on pressing BS
describe('reverseWraparound set', () => {
it('should not reverse outside of scroll margins', async () => {
// prepare buffer content
inputHandler.parseP('#####abcdefghijklmnopqrstuvwxy');
assert.deepEqual(getLines(5), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', 'uvwxy']);
assert.equal(bufferService.buffers.active.ydisp, 1);
assert.equal(bufferService.buffers.active.x, 5);
assert.equal(bufferService.buffers.active.y, 4);
inputHandler.parseP(ttyBS.repeat(100));
assert.deepEqual(getLines(5), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', ' y']);
inputHandler.parseP('\x1b[?45h');
inputHandler.parseP('uvwxy');
// set top/bottom to 1/3 (0-based)
inputHandler.parseP('\x1b[2;4r');
// place cursor below scroll bottom
bufferService.buffers.active.x = 5;
bufferService.buffers.active.y = 4;
inputHandler.parseP(ttyBS.repeat(100));
assert.deepEqual(getLines(5), ['#####', 'abcde', 'fghij', 'klmno', 'pqrst', ' ']);
inputHandler.parseP('uvwxy');
// place cursor within scroll margins
bufferService.buffers.active.x = 5;
bufferService.buffers.active.y = 3;
inputHandler.parseP(ttyBS.repeat(100));
assert.deepEqual(getLines(5), ['#####', 'abcde', ' ', ' ', ' ', 'uvwxy']);
assert.equal(bufferService.buffers.active.x, 0);
assert.equal(bufferService.buffers.active.y, bufferService.buffers.active.scrollTop); // stops at 0, scrollTop
inputHandler.parseP('fghijklmnopqrst');
// place cursor above scroll top
bufferService.buffers.active.x = 5;
bufferService.buffers.active.y = 0;
inputHandler.parseP(ttyBS.repeat(100));
assert.deepEqual(getLines(5), ['#####', ' ', 'fghij', 'klmno', 'pqrst', 'uvwxy']);
});
});
});
});
it('save and restore cursor', () => {
bufferService.buffer.x = 1;
bufferService.buffer.y = 2;
@@ -140,7 +249,7 @@ describe('InputHandler', () => {
assert.equal(coreService.decPrivateModes.bracketedPasteMode, false);
});
});
describe('regression tests', function(): void {
describe('regression tests', function (): void {
function termContent(bufferService: IBufferService, trim: boolean): string[] {
const result = [];
for (let i = 0; i < bufferService.rows; ++i) result.push(bufferService.buffer.lines.get(i)!.translateToString(trim));
@@ -430,6 +539,68 @@ describe('InputHandler', () => {
await inputHandler.parseP('¥¥¥');
assert.deepEqual(getLines(bufferService, 2), ['¥¥', '¥']);
});
// This suite cannot live in InputHandler unless Terminal.scroll moved into IBufferService
describe('SL/SR/DECIC/DECDC', () => {
it('SL (scrollLeft)', async () => {
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[ @');
assert.deepEqual(getLines(bufferService, 5), ['12345', '2345', '2345', '2345', '2345', '2345']);
inputHandler.parseP('\x1b[0 @');
assert.deepEqual(getLines(bufferService, 5), ['12345', '345', '345', '345', '345', '345']);
inputHandler.parseP('\x1b[2 @');
assert.deepEqual(getLines(bufferService, 5), ['12345', '5', '5', '5', '5', '5']);
});
it('SR (scrollRight)', async () => {
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[ A');
assert.deepEqual(getLines(bufferService, 5), ['12345', ' 1234', ' 1234', ' 1234', ' 1234', ' 1234']);
inputHandler.parseP('\x1b[0 A');
assert.deepEqual(getLines(bufferService, 5), ['12345', ' 123', ' 123', ' 123', ' 123', ' 123']);
inputHandler.parseP('\x1b[2 A');
assert.deepEqual(getLines(bufferService, 5), ['12345', ' 1', ' 1', ' 1', ' 1', ' 1']);
});
it('insertColumns (DECIC)', async () => {
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[\'}');
assert.deepEqual(getLines(bufferService, 5), ['12345', '12 34', '12 34', '12 34', '12 34', '12 34']);
inputHandler.reset();
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[1\'}');
assert.deepEqual(getLines(bufferService, 5), ['12345', '12 34', '12 34', '12 34', '12 34', '12 34']);
inputHandler.reset();
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[2\'}');
assert.deepEqual(getLines(bufferService, 5), ['12345', '12 3', '12 3', '12 3', '12 3', '12 3']);
});
it('deleteColumns (DECDC)', async () => {
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[\'~');
assert.deepEqual(getLines(bufferService, 5), ['12345', '1245', '1245', '1245', '1245', '1245']);
inputHandler.reset();
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[1\'~');
assert.deepEqual(getLines(bufferService, 5), ['12345', '1245', '1245', '1245', '1245', '1245']);
inputHandler.reset();
inputHandler.parseP('12345'.repeat(6));
inputHandler.parseP('\x1b[3;3H');
inputHandler.parseP('\x1b[2\'~');
assert.deepEqual(getLines(bufferService, 5), ['12345', '125', '125', '125', '125', '125']);
});
});
it('should fire the onScroll event', (done) => {
bufferService.onScroll(e => {
assert.equal(typeof e, 'number');
done();
});
bufferService.scroll(DEFAULT_ATTR_DATA.clone());
});
});
describe('alt screen', () => {
@@ -1240,7 +1411,7 @@ describe('InputHandler', () => {
await inputHandler.parseP('\x1b[6H\x1b[2Mm');
assert.deepEqual(getLines(bufferService), ['0', '1', '2', '3', '4', 'm', '6', '7', '8', '9']);
await inputHandler.parseP('\x1b[3H\x1b[2Mn');
assert.deepEqual(getLines(bufferService), ['0', '1', 'n', 'm', '', '', '6', '7', '8', '9']);
assert.deepEqual(getLines(bufferService), ['0', '1', 'n', 'm', '', '', '6', '7', '8', '9']);
});
});
it('should parse big chunks in smaller subchunks', async () => {
@@ -1814,13 +1985,14 @@ describe('InputHandler - async handlers', () => {
let bufferService: IBufferService;
let coreService: ICoreService;
let optionsService: MockOptionsService;
let dirtyRowService: MockDirtyRowService;
let inputHandler: TestInputHandler;
beforeEach(() => {
optionsService = new MockOptionsService();
bufferService = new BufferService(optionsService);
bufferService.resize(80, 30);
coreService = new CoreService(() => {}, bufferService, new MockLogService(), optionsService);
coreService = new CoreService(() => { }, bufferService, new MockLogService(), optionsService);
coreService.onData(data => { console.log(data); });
inputHandler = new TestInputHandler(bufferService, new MockCharsetService(), coreService, new MockDirtyRowService(), new MockLogService(), optionsService, new MockCoreMouseService(), new MockUnicodeService());
@@ -1829,7 +2001,7 @@ describe('InputHandler - async handlers', () => {
it('async CUP with CPR check', async () => {
const cup: number[][] = [];
const cpr: number[][] = [];
inputHandler.registerCsiHandler({final: 'H'}, async params => {
inputHandler.registerCsiHandler({ final: 'H' }, async params => {
cup.push(params.toArray() as number[]);
await new Promise(res => setTimeout(res, 50));
// late call of real repositioning
@@ -1855,7 +2027,7 @@ describe('InputHandler - async handlers', () => {
assert.deepEqual(getLines(bufferService, 2), ['hello world!', 'second line']);
});
it('async DCS between', async () => {
inputHandler.registerDcsHandler({final: 'a'}, async (data, params) => {
inputHandler.registerDcsHandler({ final: 'a' }, async (data, params) => {
await new Promise(res => setTimeout(res, 50));
assert.deepEqual(getLines(bufferService, 2), ['hello world!', '']);
assert.equal(data, 'some data');