diff --git a/addons/xterm-addon-attach/src/AttachAddon.api.ts b/addons/xterm-addon-attach/src/AttachAddon.api.ts index 625e1b4d..7f2ce5c1 100644 --- a/addons/xterm-addon-attach/src/AttachAddon.api.ts +++ b/addons/xterm-addon-attach/src/AttachAddon.api.ts @@ -37,7 +37,7 @@ describe('AttachAddon', () => { const server = new WebSocket.Server({ port }); server.on('connection', socket => socket.send('foo')); await page.evaluate(`window.term.loadAddon(new window.AttachAddon(new WebSocket('ws://localhost:${port}')))`); - await pollFor(page, `window.term.buffer.getLine(0).translateToString(true)`, 'foo'); + await pollFor(page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'foo'); server.close(); }); @@ -48,7 +48,7 @@ describe('AttachAddon', () => { const data = new Uint8Array([102, 111, 111]); server.on('connection', socket => socket.send(data)); await page.evaluate(`window.term.loadAddon(new window.AttachAddon(new WebSocket('ws://localhost:${port}')))`); - await pollFor(page, `window.term.buffer.getLine(0).translateToString(true)`, 'foo'); + await pollFor(page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'foo'); server.close(); }); }); diff --git a/addons/xterm-addon-search/src/SearchAddon.api.ts b/addons/xterm-addon-search/src/SearchAddon.api.ts index 21238332..521e6dfe 100644 --- a/addons/xterm-addon-search/src/SearchAddon.api.ts +++ b/addons/xterm-addon-search/src/SearchAddon.api.ts @@ -61,7 +61,7 @@ describe('Search Tests', function(): void { await page.evaluate(`window.term.writeln('package.jsonc\\n')`); await writeSync(page, 'package.json pack package.lock'); await page.evaluate(`window.search.findPrevious('pack', {incremental: true})`); - let line: string = await page.evaluate(`window.term.buffer.getLine(window.term.getSelectionPosition().startRow).translateToString()`); + let line: string = await page.evaluate(`window.term.buffer.active.getLine(window.term.getSelectionPosition().startRow).translateToString()`); let selectionPosition: { startColumn: number, startRow: number, endColumn: number, endRow: number } = await page.evaluate(`window.term.getSelectionPosition()`); // We look further ahead in the line to ensure that pack was selected from package.lock assert.deepEqual(line.substring(selectionPosition.startColumn, selectionPosition.endColumn + 8), 'package.lock'); @@ -70,7 +70,7 @@ describe('Search Tests', function(): void { assert.deepEqual(line.substring(selectionPosition.startColumn, selectionPosition.endColumn + 3), 'package.json'); await page.evaluate(`window.search.findPrevious('package.jsonc', {incremental: true})`); // We have to reevaluate line because it should have switched starting rows at this point - line = await page.evaluate(`window.term.buffer.getLine(window.term.getSelectionPosition().startRow).translateToString()`); + line = await page.evaluate(`window.term.buffer.active.getLine(window.term.getSelectionPosition().startRow).translateToString()`); selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`); assert.deepEqual(line.substring(selectionPosition.startColumn, selectionPosition.endColumn), 'package.jsonc'); }); @@ -78,7 +78,7 @@ describe('Search Tests', function(): void { await page.evaluate(`window.term.writeln('package.lock pack package.json package.ups\\n')`); await writeSync(page, 'package.jsonc'); await page.evaluate(`window.search.findNext('pack', {incremental: true})`); - let line: string = await page.evaluate(`window.term.buffer.getLine(window.term.getSelectionPosition().startRow).translateToString()`); + let line: string = await page.evaluate(`window.term.buffer.active.getLine(window.term.getSelectionPosition().startRow).translateToString()`); let selectionPosition: { startColumn: number, startRow: number, endColumn: number, endRow: number } = await page.evaluate(`window.term.getSelectionPosition()`); // We look further ahead in the line to ensure that pack was selected from package.lock assert.deepEqual(line.substring(selectionPosition.startColumn, selectionPosition.endColumn + 8), 'package.lock'); @@ -87,7 +87,7 @@ describe('Search Tests', function(): void { assert.deepEqual(line.substring(selectionPosition.startColumn, selectionPosition.endColumn + 3), 'package.json'); await page.evaluate(`window.search.findNext('package.jsonc', {incremental: true})`); // We have to reevaluate line because it should have switched starting rows at this point - line = await page.evaluate(`window.term.buffer.getLine(window.term.getSelectionPosition().startRow).translateToString()`); + line = await page.evaluate(`window.term.buffer.active.getLine(window.term.getSelectionPosition().startRow).translateToString()`); selectionPosition = await page.evaluate(`window.term.getSelectionPosition()`); assert.deepEqual(line.substring(selectionPosition.startColumn, selectionPosition.endColumn), 'package.jsonc'); }); diff --git a/addons/xterm-addon-search/src/SearchAddon.ts b/addons/xterm-addon-search/src/SearchAddon.ts index 183687ac..ba8dbc07 100644 --- a/addons/xterm-addon-search/src/SearchAddon.ts +++ b/addons/xterm-addon-search/src/SearchAddon.ts @@ -87,7 +87,7 @@ export class SearchAddon implements ITerminalAddon { // Search from startRow + 1 to end if (!result) { - for (let y = startRow + 1; y < this._terminal.buffer.baseY + this._terminal.rows; y++) { + for (let y = startRow + 1; y < this._terminal.buffer.active.baseY + this._terminal.rows; y++) { searchPosition.startRow = y; searchPosition.startCol = 0; // If the current line is wrapped line, increase index of column to ignore the previous scan @@ -135,7 +135,7 @@ export class SearchAddon implements ITerminalAddon { } const isReverseSearch = true; - let startRow = this._terminal.buffer.baseY + this._terminal.rows; + let startRow = this._terminal.buffer.active.baseY + this._terminal.rows; let startCol = this._terminal.cols; let result: ISearchResult | undefined; const incremental = searchOptions ? searchOptions.incremental : false; @@ -174,8 +174,8 @@ export class SearchAddon implements ITerminalAddon { } } // If we hit the top and didn't search from the very bottom wrap back down - if (!result && startRow !== (this._terminal.buffer.baseY + this._terminal.rows)) { - for (let y = (this._terminal.buffer.baseY + this._terminal.rows); y > startRow; y--) { + if (!result && startRow !== (this._terminal.buffer.active.baseY + this._terminal.rows)) { + for (let y = (this._terminal.buffer.active.baseY + this._terminal.rows); y > startRow; y--) { searchPosition.startRow = y; result = this._findInLine(term, searchPosition, searchOptions, isReverseSearch); if (result) { @@ -197,7 +197,7 @@ export class SearchAddon implements ITerminalAddon { private _initLinesCache(): void { const terminal = this._terminal!; if (!this._linesCache) { - this._linesCache = new Array(terminal.buffer.length); + this._linesCache = new Array(terminal.buffer.active.length); this._cursorMoveListener = terminal.onCursorMove(() => this._destroyLinesCache()); this._resizeListener = terminal.onResize(() => this._destroyLinesCache()); } @@ -249,7 +249,7 @@ export class SearchAddon implements ITerminalAddon { const col = searchPosition.startCol; // Ignore wrapped lines, only consider on unwrapped line (first row of command string). - const firstLine = terminal.buffer.getLine(row); + const firstLine = terminal.buffer.active.getLine(row); if (firstLine && firstLine.isWrapped) { if (isReverseSearch) { searchPosition.startCol += terminal.cols; @@ -311,7 +311,7 @@ export class SearchAddon implements ITerminalAddon { return; } - const line = terminal.buffer.getLine(row); + const line = terminal.buffer.active.getLine(row); if (line) { for (let i = 0; i < resultIndex; i++) { @@ -354,9 +354,9 @@ export class SearchAddon implements ITerminalAddon { let lineWrapsToNext: boolean; do { - const nextLine = terminal.buffer.getLine(lineIndex + 1); + const nextLine = terminal.buffer.active.getLine(lineIndex + 1); lineWrapsToNext = nextLine ? nextLine.isWrapped : false; - const line = terminal.buffer.getLine(lineIndex); + const line = terminal.buffer.active.getLine(lineIndex); if (!line) { break; } @@ -380,8 +380,8 @@ export class SearchAddon implements ITerminalAddon { } terminal.select(result.col, result.row, result.term.length); // If it is not in the viewport then we scroll else it just gets selected - if (result.row >= (terminal.buffer.viewportY + terminal.rows) || result.row < terminal.buffer.viewportY) { - let scroll = result.row - terminal.buffer.viewportY; + if (result.row >= (terminal.buffer.active.viewportY + terminal.rows) || result.row < terminal.buffer.active.viewportY) { + let scroll = result.row - terminal.buffer.active.viewportY; scroll = scroll - Math.floor(terminal.rows / 2); terminal.scrollLines(scroll); } diff --git a/addons/xterm-addon-serialize/src/SerializeAddon.ts b/addons/xterm-addon-serialize/src/SerializeAddon.ts index 1d011726..445c4860 100644 --- a/addons/xterm-addon-serialize/src/SerializeAddon.ts +++ b/addons/xterm-addon-serialize/src/SerializeAddon.ts @@ -175,8 +175,8 @@ export class SerializeAddon implements ITerminalAddon { throw new Error('Cannot use addon until it has been loaded'); } - const maxRows = this._terminal.buffer.length; - const handler = new StringSerializeHandler(this._terminal.buffer); + const maxRows = this._terminal.buffer.active.length; + const handler = new StringSerializeHandler(this._terminal.buffer.active); rows = (rows === undefined) ? maxRows : constrain(rows, 0, maxRows); diff --git a/addons/xterm-addon-web-links/src/WebLinkProvider.ts b/addons/xterm-addon-web-links/src/WebLinkProvider.ts index ea43aae6..23dc8560 100644 --- a/addons/xterm-addon-web-links/src/WebLinkProvider.ts +++ b/addons/xterm-addon-web-links/src/WebLinkProvider.ts @@ -84,7 +84,7 @@ export class LinkComputer { let prevLinesToWrap: boolean; do { - const line = terminal.buffer.getLine(lineIndex); + const line = terminal.buffer.active.getLine(lineIndex); if (!line) { break; } @@ -99,9 +99,9 @@ export class LinkComputer { const startLineIndex = lineIndex; do { - const nextLine = terminal.buffer.getLine(lineIndex + 1); + const nextLine = terminal.buffer.active.getLine(lineIndex + 1); lineWrapsToNext = nextLine ? nextLine.isWrapped : false; - const line = terminal.buffer.getLine(lineIndex); + const line = terminal.buffer.active.getLine(lineIndex); if (!line) { break; } diff --git a/addons/xterm-addon-webgl/src/GlyphRenderer.ts b/addons/xterm-addon-webgl/src/GlyphRenderer.ts index 6c67febb..f8eed3ae 100644 --- a/addons/xterm-addon-webgl/src/GlyphRenderer.ts +++ b/addons/xterm-addon-webgl/src/GlyphRenderer.ts @@ -250,7 +250,7 @@ export class GlyphRenderer { private _updateSelectionRange(startCol: number, endCol: number, y: number, model: IRenderModel, bg: number): void { const terminal = this._terminal; - const row = y + terminal.buffer.viewportY; + const row = y + terminal.buffer.active.viewportY; let line: IBufferLine | undefined; for (let x = startCol; x < endCol; x++) { const offset = (y * this._terminal.cols + x) * RENDER_MODEL_INDICIES_PER_CELL; @@ -281,7 +281,7 @@ export class GlyphRenderer { } if (code & COMBINED_CHAR_BIT_MASK) { if (!line) { - line = terminal.buffer.getLine(row); + line = terminal.buffer.active.getLine(row); } const chars = line!.getCell(x)!.getChars(); this._updateCell(this._vertices.selectionAttributes, x, y, model.cells[offset], bg, fg, chars); diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.ts b/addons/xterm-addon-webgl/src/WebglRenderer.ts index aba9c456..08754efa 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.ts @@ -302,8 +302,8 @@ export class WebglRenderer extends Disposable implements IRenderer { } // Translate from buffer position to viewport position - const viewportStartRow = start[1] - terminal.buffer.viewportY; - const viewportEndRow = end[1] - terminal.buffer.viewportY; + const viewportStartRow = start[1] - terminal.buffer.active.viewportY; + const viewportEndRow = end[1] - terminal.buffer.active.viewportY; const viewportCappedStartRow = Math.max(viewportStartRow, 0); const viewportCappedEndRow = Math.min(viewportEndRow, terminal.rows - 1); diff --git a/addons/xterm-addon-webgl/src/renderLayer/CursorRenderLayer.ts b/addons/xterm-addon-webgl/src/renderLayer/CursorRenderLayer.ts index 2ade8007..6af2b7d7 100644 --- a/addons/xterm-addon-webgl/src/renderLayer/CursorRenderLayer.ts +++ b/addons/xterm-addon-webgl/src/renderLayer/CursorRenderLayer.ts @@ -76,14 +76,14 @@ export class CursorRenderLayer extends BaseRenderLayer { if (this._cursorBlinkStateManager) { this._cursorBlinkStateManager.pause(); } - this._onRequestRefreshRowsEvent.fire({ start: terminal.buffer.cursorY, end: terminal.buffer.cursorY }); + this._onRequestRefreshRowsEvent.fire({ start: terminal.buffer.active.cursorY, end: terminal.buffer.active.cursorY }); } public onFocus(terminal: Terminal): void { if (this._cursorBlinkStateManager) { this._cursorBlinkStateManager.resume(terminal); } else { - this._onRequestRefreshRowsEvent.fire({ start: terminal.buffer.cursorY, end: terminal.buffer.cursorY }); + this._onRequestRefreshRowsEvent.fire({ start: terminal.buffer.active.cursorY, end: terminal.buffer.active.cursorY }); } } @@ -100,7 +100,7 @@ export class CursorRenderLayer extends BaseRenderLayer { } // Request a refresh from the terminal as management of rendering is being // moved back to the terminal - this._onRequestRefreshRowsEvent.fire({ start: terminal.buffer.cursorY, end: terminal.buffer.cursorY }); + this._onRequestRefreshRowsEvent.fire({ start: terminal.buffer.active.cursorY, end: terminal.buffer.active.cursorY }); } public onCursorMove(terminal: Terminal): void { @@ -125,11 +125,11 @@ export class CursorRenderLayer extends BaseRenderLayer { return; } - const cursorY = terminal.buffer.baseY + terminal.buffer.cursorY; - const viewportRelativeCursorY = cursorY - terminal.buffer.viewportY; + const cursorY = terminal.buffer.active.baseY + terminal.buffer.active.cursorY; + const viewportRelativeCursorY = cursorY - terminal.buffer.active.viewportY; // in case cursor.x == cols adjust visual cursor to cols - 1 - const cursorX = Math.min(terminal.buffer.cursorX, terminal.cols - 1); + const cursorX = Math.min(terminal.buffer.active.cursorX, terminal.cols - 1); // Don't draw the cursor if it's off-screen if (viewportRelativeCursorY < 0 || viewportRelativeCursorY >= terminal.rows) { diff --git a/src/public/Terminal.ts b/src/public/Terminal.ts index 5535bd47..a4d841b4 100644 --- a/src/public/Terminal.ts +++ b/src/public/Terminal.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { Terminal as ITerminalApi, ITerminalOptions, IMarker, IDisposable, ILinkMatcherOptions, ITheme, ILocalizableStrings, ITerminalAddon, ISelectionPosition, IBuffer as IBufferApi, IBufferSet as IBufferSetApi, IBufferLine as IBufferLineApi, IBufferCell as IBufferCellApi, IParser, IFunctionIdentifier, ILinkProvider, IUnicodeHandling, IUnicodeVersionProvider } from 'xterm'; +import { Terminal as ITerminalApi, ITerminalOptions, IMarker, IDisposable, ILinkMatcherOptions, ITheme, ILocalizableStrings, ITerminalAddon, ISelectionPosition, IBuffer as IBufferApi, IBufferNamespace as IBufferNamespaceApi, IBufferLine as IBufferLineApi, IBufferCell as IBufferCellApi, IParser, IFunctionIdentifier, ILinkProvider, IUnicodeHandling, IUnicodeVersionProvider } from 'xterm'; import { ITerminal } from '../Types'; import { IBufferLine, ICellData } from 'common/Types'; import { IBuffer, IBufferSet } from 'common/buffer/Types'; @@ -48,8 +48,7 @@ export class Terminal implements ITerminalApi { public get textarea(): HTMLTextAreaElement | undefined { return this._core.textarea; } public get rows(): number { return this._core.rows; } public get cols(): number { return this._core.cols; } - public get buffer(): IBufferApi { return new BufferApiView(this._core.buffer); } - public get buffers(): IBufferSetApi { return new BufferSetApiView(this._core.buffers); } + public get buffer(): IBufferNamespaceApi { return new BufferNamespaceApi(this._core.buffers); } public get markers(): ReadonlyArray { return this._core.markers; } public blur(): void { this._core.blur(); @@ -194,8 +193,13 @@ export class Terminal implements ITerminalApi { } class BufferApiView implements IBufferApi { - constructor(private _buffer: IBuffer) { } + constructor(private _buffer: IBuffer, private _buffers: IBufferSet) { } + public get type(): 'normal' | 'alternate' { + if (this._buffers.normal === this._buffer) { return 'normal'; } + else if (this._buffers.alt === this._buffer) { return 'alternate'; } + throw new Error('Unknown buffer type'); + } public get cursorY(): number { return this._buffer.y; } public get cursorX(): number { return this._buffer.x; } public get viewportY(): number { return this._buffer.ydisp; } @@ -211,20 +215,17 @@ class BufferApiView implements IBufferApi { public getNullCell(): IBufferCellApi { return new CellData(); } } -class BufferSetApiView implements IBufferSetApi { +class BufferNamespaceApi implements IBufferNamespaceApi { constructor(private _buffers: IBufferSet) { } - public get alt(): IBufferApi { return new BufferApiView(this._buffers.alt); } - public get active(): IBufferApi { return new BufferApiView(this._buffers.active); } - public get normal(): IBufferApi { return new BufferApiView(this._buffers.normal); } + public get alternate(): IBufferApi { return new BufferApiView(this._buffers.alt, this._buffers); } + public get active(): IBufferApi { return new BufferApiView(this._buffers.active, this._buffers); } + public get normal(): IBufferApi { return new BufferApiView(this._buffers.normal, this._buffers); } - public get onBufferActivate(): IEvent<{ activeBuffer: IBufferApi, inactiveBuffer: IBufferApi }> { - return (listener: (arg1: { activeBuffer: IBufferApi, inactiveBuffer: IBufferApi }, arg2: void) => any) => { - return this._buffers.onBufferActivate((innerArg: { activeBuffer: IBuffer, inactiveBuffer: IBuffer }) => { - listener({ - activeBuffer: new BufferApiView(innerArg.activeBuffer), - inactiveBuffer: new BufferApiView(innerArg.inactiveBuffer) - }); + public get onBufferChange(): IEvent { + return (listener: (buffer: IBufferApi, unused: void) => any): IDisposable => { + return this._buffers.onBufferActivate((arg1: { activeBuffer: IBuffer, inactiveBuffer: IBuffer }) => { + listener(new BufferApiView(arg1.activeBuffer, this._buffers)); }); }; } diff --git a/test/api/CharWidth.api.ts b/test/api/CharWidth.api.ts index b5cb5838..fbc71b46 100644 --- a/test/api/CharWidth.api.ts +++ b/test/api/CharWidth.api.ts @@ -79,7 +79,7 @@ async function sumWidths(start: number, end: number, sentinel: string): Promise< await page.evaluate(` (function() { window.result = 0; - const buffer = window.term.buffer; + const buffer = window.term.buffer.active; for (let i = ${start}; i < ${end}; i++) { const line = buffer.getLine(i); let j = 0; diff --git a/test/api/InputHandler.api.ts b/test/api/InputHandler.api.ts index d4018d90..c6d9939c 100644 --- a/test/api/InputHandler.api.ts +++ b/test/api/InputHandler.api.ts @@ -165,7 +165,7 @@ describe('InputHandler Integration Tests', function(): void { window.term.reset() window.term.write('1\\n2\\n3\\n4\\n5${fixture}\x1b[3J') `); - await pollFor(page, () => page.evaluate(`window.term.buffer.length`), 5); + await pollFor(page, () => page.evaluate(`window.term.buffer.active.length`), 5); await pollFor(page, () => getLinesAsArray(5), [' 4', ' 5', 'abc', 'def', 'ghi']); }); @@ -194,7 +194,7 @@ describe('InputHandler Integration Tests', function(): void { window.term.reset() window.term.write('1\\n2\\n3\\n4\\n5${fixture}\x1b[?3J') `); - await pollFor(page, () => page.evaluate(`window.term.buffer.length`), 5); + await pollFor(page, () => page.evaluate(`window.term.buffer.active.length`), 5); await pollFor(page, () => getLinesAsArray(5), [' 4', ' 5', 'abc', 'def', 'ghi']); }); @@ -240,7 +240,7 @@ describe('InputHandler Integration Tests', function(): void { it('Report Cursor Position (CPR) - CSI 6 n', async function(): Promise { await page.evaluate(`window.term.write('\\n\\nfoo')`); await pollFor(page, () => page.evaluate(` - [window.term.buffer.cursorY, window.term.buffer.cursorX] + [window.term.buffer.active.cursorY, window.term.buffer.active.cursorX] `), [2, 3]); await page.evaluate(` window.term.onData(e => window.result = e); @@ -252,7 +252,7 @@ describe('InputHandler Integration Tests', function(): void { it('Report Cursor Position (DECXCPR) - CSI ? 6 n', async function(): Promise { await page.evaluate(`window.term.write('\\n\\nfoo')`); await pollFor(page, () => page.evaluate(` - [window.term.buffer.cursorY, window.term.buffer.cursorX] + [window.term.buffer.active.cursorY, window.term.buffer.active.cursorX] `), [2, 3]); await page.evaluate(` window.term.onData(e => window.result = e); @@ -410,7 +410,7 @@ describe('InputHandler Integration Tests', function(): void { async function getLinesAsArray(count: number, start: number = 0): Promise { let text = ''; for (let i = start; i < start + count; i++) { - text += `window.term.buffer.getLine(${i}).translateToString(true), `; + text += `window.term.buffer.active.getLine(${i}).translateToString(true),`; } return await page.evaluate(`[${text}]`); } @@ -430,10 +430,10 @@ async function simulatePaste(text: string): Promise { async function getCursor(): Promise<{ col: number, row: number }> { return page.evaluate(` - (function() { - return { col: term.buffer.cursorX, row: term.buffer.cursorY }; - })(); - `); + (function() { + return {col: term.buffer.active.cursorX, row: term.buffer.active.cursorY}; + })(); + `); } async function getDimensions(): Promise { diff --git a/test/api/Terminal.api.ts b/test/api/Terminal.api.ts index fce17511..2798f653 100644 --- a/test/api/Terminal.api.ts +++ b/test/api/Terminal.api.ts @@ -41,7 +41,7 @@ describe('API Integration Tests', function(): void { window.term.write('bar'); window.term.write('文'); `); - await pollFor(page, `window.term.buffer.getLine(0).translateToString(true)`, 'foobar文'); + await pollFor(page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'foobar文'); }); it('write with callback', async () => { @@ -51,7 +51,7 @@ describe('API Integration Tests', function(): void { window.term.write('bar', () => { window.__x += 'b'; }); window.term.write('文', () => { window.__x += 'c'; }); `); - await pollFor(page, `window.term.buffer.getLine(0).translateToString(true)`, 'foobar文'); + await pollFor(page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'foobar文'); await pollFor(page, `window.__x`, 'abc'); }); @@ -65,7 +65,7 @@ describe('API Integration Tests', function(): void { // 文 window.term.write(new Uint8Array([230, 150, 135])); `); - await pollFor(page, `window.term.buffer.getLine(0).translateToString(true)`, 'foobar文'); + await pollFor(page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'foobar文'); }); it('write - bytes (UTF8) with callback', async () => { @@ -78,7 +78,7 @@ describe('API Integration Tests', function(): void { // 文 window.term.write(new Uint8Array([230, 150, 135]), () => { window.__x += 'C'; }); `); - await pollFor(page, `window.term.buffer.getLine(0).translateToString(true)`, 'foobar文'); + await pollFor(page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'foobar文'); await pollFor(page, `window.__x`, 'ABC'); }); @@ -89,9 +89,9 @@ describe('API Integration Tests', function(): void { window.term.writeln('bar'); window.term.writeln('文'); `); - await pollFor(page, `window.term.buffer.getLine(0).translateToString(true)`, 'foo'); - await pollFor(page, `window.term.buffer.getLine(1).translateToString(true)`, 'bar'); - await pollFor(page, `window.term.buffer.getLine(2).translateToString(true)`, '文'); + await pollFor(page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'foo'); + await pollFor(page, `window.term.buffer.active.getLine(1).translateToString(true)`, 'bar'); + await pollFor(page, `window.term.buffer.active.getLine(2).translateToString(true)`, '文'); }); it('writeln with callback', async () => { @@ -101,9 +101,9 @@ describe('API Integration Tests', function(): void { window.term.writeln('bar', () => { window.__x += '2'; }); window.term.writeln('文', () => { window.__x += '3'; }); `); - await pollFor(page, `window.term.buffer.getLine(0).translateToString(true)`, 'foo'); - await pollFor(page, `window.term.buffer.getLine(1).translateToString(true)`, 'bar'); - await pollFor(page, `window.term.buffer.getLine(2).translateToString(true)`, '文'); + await pollFor(page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'foo'); + await pollFor(page, `window.term.buffer.active.getLine(1).translateToString(true)`, 'bar'); + await pollFor(page, `window.term.buffer.active.getLine(2).translateToString(true)`, '文'); await pollFor(page, `window.__x`, '123'); }); @@ -114,9 +114,9 @@ describe('API Integration Tests', function(): void { window.term.writeln(new Uint8Array([98, 97, 114])); window.term.writeln(new Uint8Array([230, 150, 135])); `); - await pollFor(page, `window.term.buffer.getLine(0).translateToString(true)`, 'foo'); - await pollFor(page, `window.term.buffer.getLine(1).translateToString(true)`, 'bar'); - await pollFor(page, `window.term.buffer.getLine(2).translateToString(true)`, '文'); + await pollFor(page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'foo'); + await pollFor(page, `window.term.buffer.active.getLine(1).translateToString(true)`, 'bar'); + await pollFor(page, `window.term.buffer.active.getLine(2).translateToString(true)`, '文'); }); it('paste', async () => { @@ -144,10 +144,10 @@ describe('API Integration Tests', function(): void { `); await pollFor(page, `window.parsed`, 9); await page.evaluate(`window.term.clear()`); - await pollFor(page, `window.term.buffer.length`, 5); - await pollFor(page, `window.term.buffer.getLine(0).translateToString(true)`, 'test9'); + await pollFor(page, `window.term.buffer.active.length`, 5); + await pollFor(page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'test9'); for (let i = 1; i < 5; i++) { - await pollFor(page, `window.term.buffer.getLine(${i}).translateToString(true)`, ''); + await pollFor(page, `window.term.buffer.active.getLine(${i}).translateToString(true)`, ''); } }); @@ -400,113 +400,113 @@ describe('API Integration Tests', function(): void { describe('buffer', () => { it('cursorX, cursorY', async () => { await openTerminal(page, { rows: 5, cols: 5 }); - assert.equal(await page.evaluate(`window.term.buffer.cursorX`), 0); - assert.equal(await page.evaluate(`window.term.buffer.cursorY`), 0); + assert.equal(await page.evaluate(`window.term.buffer.active.cursorX`), 0); + assert.equal(await page.evaluate(`window.term.buffer.active.cursorY`), 0); await writeSync(page, 'foo'); - assert.equal(await page.evaluate(`window.term.buffer.cursorX`), 3); - assert.equal(await page.evaluate(`window.term.buffer.cursorY`), 0); + assert.equal(await page.evaluate(`window.term.buffer.active.cursorX`), 3); + assert.equal(await page.evaluate(`window.term.buffer.active.cursorY`), 0); await writeSync(page, '\\n'); - assert.equal(await page.evaluate(`window.term.buffer.cursorX`), 3); - assert.equal(await page.evaluate(`window.term.buffer.cursorY`), 1); + assert.equal(await page.evaluate(`window.term.buffer.active.cursorX`), 3); + assert.equal(await page.evaluate(`window.term.buffer.active.cursorY`), 1); await writeSync(page, '\\r'); - assert.equal(await page.evaluate(`window.term.buffer.cursorX`), 0); - assert.equal(await page.evaluate(`window.term.buffer.cursorY`), 1); + assert.equal(await page.evaluate(`window.term.buffer.active.cursorX`), 0); + assert.equal(await page.evaluate(`window.term.buffer.active.cursorY`), 1); await writeSync(page, 'abcde'); - assert.equal(await page.evaluate(`window.term.buffer.cursorX`), 5); - assert.equal(await page.evaluate(`window.term.buffer.cursorY`), 1); + assert.equal(await page.evaluate(`window.term.buffer.active.cursorX`), 5); + assert.equal(await page.evaluate(`window.term.buffer.active.cursorY`), 1); await writeSync(page, '\\n\\r\\n\\n\\n\\n\\n'); - assert.equal(await page.evaluate(`window.term.buffer.cursorX`), 0); - assert.equal(await page.evaluate(`window.term.buffer.cursorY`), 4); + assert.equal(await page.evaluate(`window.term.buffer.active.cursorX`), 0); + assert.equal(await page.evaluate(`window.term.buffer.active.cursorY`), 4); }); it('viewportY', async () => { await openTerminal(page, { rows: 5 }); - assert.equal(await page.evaluate(`window.term.buffer.viewportY`), 0); + assert.equal(await page.evaluate(`window.term.buffer.active.viewportY`), 0); await writeSync(page, '\\n\\n\\n\\n'); - assert.equal(await page.evaluate(`window.term.buffer.viewportY`), 0); + assert.equal(await page.evaluate(`window.term.buffer.active.viewportY`), 0); await writeSync(page, '\\n'); - assert.equal(await page.evaluate(`window.term.buffer.viewportY`), 1); + assert.equal(await page.evaluate(`window.term.buffer.active.viewportY`), 1); await writeSync(page, '\\n\\n\\n\\n'); - assert.equal(await page.evaluate(`window.term.buffer.viewportY`), 5); + assert.equal(await page.evaluate(`window.term.buffer.active.viewportY`), 5); await page.evaluate(`window.term.scrollLines(-1)`); - assert.equal(await page.evaluate(`window.term.buffer.viewportY`), 4); + assert.equal(await page.evaluate(`window.term.buffer.active.viewportY`), 4); await page.evaluate(`window.term.scrollToTop()`); - assert.equal(await page.evaluate(`window.term.buffer.viewportY`), 0); + assert.equal(await page.evaluate(`window.term.buffer.active.viewportY`), 0); }); it('baseY', async () => { await openTerminal(page, { rows: 5 }); - assert.equal(await page.evaluate(`window.term.buffer.baseY`), 0); + assert.equal(await page.evaluate(`window.term.buffer.active.baseY`), 0); await writeSync(page, '\\n\\n\\n\\n'); - assert.equal(await page.evaluate(`window.term.buffer.baseY`), 0); + assert.equal(await page.evaluate(`window.term.buffer.active.baseY`), 0); await writeSync(page, '\\n'); - assert.equal(await page.evaluate(`window.term.buffer.baseY`), 1); + assert.equal(await page.evaluate(`window.term.buffer.active.baseY`), 1); await writeSync(page, '\\n\\n\\n\\n'); - assert.equal(await page.evaluate(`window.term.buffer.baseY`), 5); + assert.equal(await page.evaluate(`window.term.buffer.active.baseY`), 5); await page.evaluate(`window.term.scrollLines(-1)`); - assert.equal(await page.evaluate(`window.term.buffer.baseY`), 5); + assert.equal(await page.evaluate(`window.term.buffer.active.baseY`), 5); await page.evaluate(`window.term.scrollToTop()`); - assert.equal(await page.evaluate(`window.term.buffer.baseY`), 5); + assert.equal(await page.evaluate(`window.term.buffer.active.baseY`), 5); }); it('length', async () => { await openTerminal(page, { rows: 5 }); - assert.equal(await page.evaluate(`window.term.buffer.length`), 5); + assert.equal(await page.evaluate(`window.term.buffer.active.length`), 5); await writeSync(page, '\\n\\n\\n\\n'); - assert.equal(await page.evaluate(`window.term.buffer.length`), 5); + assert.equal(await page.evaluate(`window.term.buffer.active.length`), 5); await writeSync(page, '\\n'); - assert.equal(await page.evaluate(`window.term.buffer.length`), 6); + assert.equal(await page.evaluate(`window.term.buffer.active.length`), 6); await writeSync(page, '\\n\\n\\n\\n'); - assert.equal(await page.evaluate(`window.term.buffer.length`), 10); + assert.equal(await page.evaluate(`window.term.buffer.active.length`), 10); }); describe('getLine', () => { it('invalid index', async () => { await openTerminal(page, { rows: 5 }); - assert.equal(await page.evaluate(`window.term.buffer.getLine(-1)`), undefined); - assert.equal(await page.evaluate(`window.term.buffer.getLine(5)`), undefined); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(-1)`), undefined); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(5)`), undefined); }); it('isWrapped', async () => { await openTerminal(page, { cols: 5 }); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).isWrapped`), false); - assert.equal(await page.evaluate(`window.term.buffer.getLine(1).isWrapped`), false); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).isWrapped`), false); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(1).isWrapped`), false); await writeSync(page, 'abcde'); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).isWrapped`), false); - assert.equal(await page.evaluate(`window.term.buffer.getLine(1).isWrapped`), false); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).isWrapped`), false); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(1).isWrapped`), false); await writeSync(page, 'f'); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).isWrapped`), false); - assert.equal(await page.evaluate(`window.term.buffer.getLine(1).isWrapped`), true); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).isWrapped`), false); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(1).isWrapped`), true); }); it('translateToString', async () => { await openTerminal(page, { cols: 5 }); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).translateToString()`), ' '); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).translateToString(true)`), ''); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).translateToString()`), ' '); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).translateToString(true)`), ''); await writeSync(page, 'foo'); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).translateToString()`), 'foo '); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).translateToString(true)`), 'foo'); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).translateToString()`), 'foo '); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).translateToString(true)`), 'foo'); await writeSync(page, 'bar'); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).translateToString()`), 'fooba'); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).translateToString(true)`), 'fooba'); - assert.equal(await page.evaluate(`window.term.buffer.getLine(1).translateToString(true)`), 'r'); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).translateToString(false, 1)`), 'ooba'); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).translateToString(false, 1, 3)`), 'oo'); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).translateToString()`), 'fooba'); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).translateToString(true)`), 'fooba'); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(1).translateToString(true)`), 'r'); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).translateToString(false, 1)`), 'ooba'); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).translateToString(false, 1, 3)`), 'oo'); }); it('getCell', async () => { await openTerminal(page, { cols: 5 }); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).getCell(-1)`), undefined); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).getCell(5)`), undefined); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).getCell(0).getChars()`), ''); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).getCell(0).getWidth()`), 1); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).getCell(-1)`), undefined); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).getCell(5)`), undefined); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).getCell(0).getChars()`), ''); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).getCell(0).getWidth()`), 1); await writeSync(page, 'a文'); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).getCell(0).getChars()`), 'a'); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).getCell(0).getWidth()`), 1); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).getCell(1).getChars()`), '文'); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).getCell(1).getWidth()`), 2); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).getCell(2).getChars()`), ''); - assert.equal(await page.evaluate(`window.term.buffer.getLine(0).getCell(2).getWidth()`), 0); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).getCell(0).getChars()`), 'a'); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).getCell(0).getWidth()`), 1); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).getCell(1).getChars()`), '文'); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).getCell(1).getWidth()`), 2); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).getCell(2).getChars()`), ''); + assert.equal(await page.evaluate(`window.term.buffer.active.getLine(0).getCell(2).getWidth()`), 0); }); }); }); @@ -634,7 +634,7 @@ describe('API Integration Tests', function(): void { window.calls.push('provide ' + position.x + ',' + position.y); cb({ range: { start: position, end: position }, - text: window.term.buffer.getLine(position.y - 1).getCell(position.x - 1).getChars(), + text: window.term.buffer.active.getLine(position.y - 1).getCell(position.x - 1).getChars(), activate: (_, text) => window.calls.push('activate ' + text), hover: () => window.calls.push('hover'), leave: () => window.calls.push('leave') diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 4613677d..a7ac9fe6 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -574,12 +574,7 @@ declare module 'xterm' { * normal buffer or the alt buffer depending on what's running in the * terminal. */ - readonly buffer: IBuffer; - - /** - * (EXPERIMENTAL) The terminal's current bufferSet. - */ - readonly buffers: IBufferSet; + readonly buffer: IBufferNamespace; /** * (EXPERIMENTAL) Get all markers registered against the buffer. If the alt @@ -1173,6 +1168,10 @@ declare module 'xterm' { * Represents a terminal buffer. */ interface IBuffer { + /** + * The type of the buffer. + */ + readonly type: 'normal' | 'alternate'; /** * The y position of the cursor. This ranges between `0` (when the * cursor is at baseY) and `Terminal.rows - 1` (when the cursor is on the @@ -1222,12 +1221,12 @@ declare module 'xterm' { getNullCell(): IBufferCell; } - interface IBufferSet { - readonly alt: IBuffer; + interface IBufferNamespace { + readonly alternate: IBuffer; readonly normal: IBuffer; readonly active: IBuffer; - onBufferActivate: IEvent<{ activeBuffer: IBuffer, inactiveBuffer: IBuffer }>; + onBufferChange: IEvent; } /**