Create terminal.buffer convenience attribute

This commit is contained in:
Paris Kasidiaris
2017-07-16 03:47:15 +03:00
committed by Paris Kasidiaris
parent 95cb6f30bb
commit 8ede1fc9d2
5 changed files with 84 additions and 69 deletions
+6 -2
View File
@@ -4,13 +4,15 @@
import { ITerminal } from './Interfaces';
import { Buffer } from './Buffer';
import { EventEmitter } from './EventEmitter';
export class BufferSet {
export class BufferSet extends EventEmitter {
private _normal: Buffer;
private _alt: Buffer;
private _activeBuffer: Buffer;
constructor(private _terminal: ITerminal) {
super();
this._normal = new Buffer(this._terminal);
this._alt = new Buffer(this._terminal);
this._activeBuffer = this._normal;
@@ -36,9 +38,11 @@ export class BufferSet {
public activateNormalBuffer(): void {
this._activeBuffer = this._normal;
this.emit('activate', this._normal);
}
public activateAltBuffer(): void {
this._activeBuffer = this._normal;
this._activeBuffer = this._alt;
this.emit('activate', this._alt);
}
}
+35 -35
View File
@@ -33,15 +33,15 @@ export class InputHandler implements IInputHandler {
// FIXME: needs handling after cursor jumps
if (!ch_width && this._terminal.x) {
// dont overflow left
if (this._terminal.lines.get(row)[this._terminal.x - 1]) {
if (!this._terminal.lines.get(row)[this._terminal.x - 1][2]) {
if (this._terminal.buffer.lines.get(row)[this._terminal.x - 1]) {
if (!this._terminal.buffer.lines.get(row)[this._terminal.x - 1][2]) {
// found empty cell after fullwidth, need to go 2 cells back
if (this._terminal.lines.get(row)[this._terminal.x - 2])
this._terminal.lines.get(row)[this._terminal.x - 2][1] += char;
if (this._terminal.buffer.lines.get(row)[this._terminal.x - 2])
this._terminal.buffer.lines.get(row)[this._terminal.x - 2][1] += char;
} else {
this._terminal.lines.get(row)[this._terminal.x - 1][1] += char;
this._terminal.buffer.lines.get(row)[this._terminal.x - 1][1] += char;
}
this._terminal.updateRange(this._terminal.y);
}
@@ -77,25 +77,25 @@ export class InputHandler implements IInputHandler {
for (let moves = 0; moves < ch_width; ++moves) {
// remove last cell, if it's width is 0
// we have to adjust the second last cell as well
const removed = this._terminal.lines.get(this._terminal.y + this._terminal.ybase).pop();
const removed = this._terminal.buffer.lines.get(this._terminal.y + this._terminal.ybase).pop();
if (removed[2] === 0
&& this._terminal.lines.get(row)[this._terminal.cols - 2]
&& this._terminal.lines.get(row)[this._terminal.cols - 2][2] === 2) {
this._terminal.lines.get(row)[this._terminal.cols - 2] = [this._terminal.curAttr, ' ', 1];
&& this._terminal.buffer.lines.get(row)[this._terminal.cols - 2]
&& this._terminal.buffer.lines.get(row)[this._terminal.cols - 2][2] === 2) {
this._terminal.buffer.lines.get(row)[this._terminal.cols - 2] = [this._terminal.curAttr, ' ', 1];
}
// insert empty cell at cursor
this._terminal.lines.get(row).splice(this._terminal.x, 0, [this._terminal.curAttr, ' ', 1]);
this._terminal.buffer.lines.get(row).splice(this._terminal.x, 0, [this._terminal.curAttr, ' ', 1]);
}
}
this._terminal.lines.get(row)[this._terminal.x] = [this._terminal.curAttr, char, ch_width];
this._terminal.buffer.lines.get(row)[this._terminal.x] = [this._terminal.curAttr, char, ch_width];
this._terminal.x++;
this._terminal.updateRange(this._terminal.y);
// fullwidth char - set next cell width to zero and advance cursor
if (ch_width === 2) {
this._terminal.lines.get(row)[this._terminal.x] = [this._terminal.curAttr, '', 0];
this._terminal.buffer.lines.get(row)[this._terminal.x] = [this._terminal.curAttr, '', 0];
this._terminal.x++;
}
}
@@ -194,8 +194,8 @@ export class InputHandler implements IInputHandler {
ch = [this._terminal.eraseAttr(), ' ', 1]; // xterm
while (param-- && j < this._terminal.cols) {
this._terminal.lines.get(row).splice(j++, 0, ch);
this._terminal.lines.get(row).pop();
this._terminal.buffer.lines.get(row).splice(j++, 0, ch);
this._terminal.buffer.lines.get(row).pop();
}
}
@@ -392,9 +392,9 @@ export class InputHandler implements IInputHandler {
break;
case 3:
// Clear scrollback (everything not in viewport)
const scrollBackSize = this._terminal.lines.length - this._terminal.rows;
const scrollBackSize = this._terminal.buffer.lines.length - this._terminal.rows;
if (scrollBackSize > 0) {
this._terminal.lines.trimStart(scrollBackSize);
this._terminal.buffer.lines.trimStart(scrollBackSize);
this._terminal.ybase = Math.max(this._terminal.ybase - scrollBackSize, 0);
this._terminal.ydisp = Math.max(this._terminal.ydisp - scrollBackSize, 0);
// Force a scroll event to refresh viewport
@@ -446,9 +446,9 @@ export class InputHandler implements IInputHandler {
j = this._terminal.rows - 1 + this._terminal.ybase - j + 1;
while (param--) {
if (this._terminal.lines.length === this._terminal.lines.maxLength) {
if (this._terminal.buffer.lines.length === this._terminal.buffer.lines.maxLength) {
// Trim the start of lines to make room for the new line
this._terminal.lines.trimStart(1);
this._terminal.buffer.lines.trimStart(1);
this._terminal.ybase--;
this._terminal.ydisp--;
row--;
@@ -456,8 +456,8 @@ export class InputHandler implements IInputHandler {
}
// test: echo -e '\e[44m\e[1L\e[0m'
// blankLine(true) - xterm/linux behavior
this._terminal.lines.splice(row, 0, this._terminal.blankLine(true));
this._terminal.lines.splice(j, 1);
this._terminal.buffer.lines.splice(row, 0, this._terminal.blankLine(true));
this._terminal.buffer.lines.splice(j, 1);
}
// this.maxRange();
@@ -482,16 +482,16 @@ export class InputHandler implements IInputHandler {
j = this._terminal.rows - 1 + this._terminal.ybase - j;
while (param--) {
if (this._terminal.lines.length === this._terminal.lines.maxLength) {
if (this._terminal.buffer.lines.length === this._terminal.buffer.lines.maxLength) {
// Trim the start of lines to make room for the new line
this._terminal.lines.trimStart(1);
this._terminal.buffer.lines.trimStart(1);
this._terminal.ybase -= 1;
this._terminal.ydisp -= 1;
}
// test: echo -e '\e[44m\e[1M\e[0m'
// blankLine(true) - xterm/linux behavior
this._terminal.lines.splice(j + 1, 0, this._terminal.blankLine(true));
this._terminal.lines.splice(row, 1);
this._terminal.buffer.lines.splice(j + 1, 0, this._terminal.blankLine(true));
this._terminal.buffer.lines.splice(row, 1);
}
// this.maxRange();
@@ -515,8 +515,8 @@ export class InputHandler implements IInputHandler {
ch = [this._terminal.eraseAttr(), ' ', 1]; // xterm
while (param--) {
this._terminal.lines.get(row).splice(this._terminal.x, 1);
this._terminal.lines.get(row).push(ch);
this._terminal.buffer.lines.get(row).splice(this._terminal.x, 1);
this._terminal.buffer.lines.get(row).push(ch);
}
}
@@ -526,8 +526,8 @@ export class InputHandler implements IInputHandler {
public scrollUp(params: number[]): void {
let param = params[0] || 1;
while (param--) {
this._terminal.lines.splice(this._terminal.ybase + this._terminal.scrollTop, 1);
this._terminal.lines.splice(this._terminal.ybase + this._terminal.scrollBottom, 0, this._terminal.blankLine());
this._terminal.buffer.lines.splice(this._terminal.ybase + this._terminal.scrollTop, 1);
this._terminal.buffer.lines.splice(this._terminal.ybase + this._terminal.scrollBottom, 0, this._terminal.blankLine());
}
// this.maxRange();
this._terminal.updateRange(this._terminal.scrollTop);
@@ -540,8 +540,8 @@ export class InputHandler implements IInputHandler {
public scrollDown(params: number[]): void {
let param = params[0] || 1;
while (param--) {
this._terminal.lines.splice(this._terminal.ybase + this._terminal.scrollBottom, 1);
this._terminal.lines.splice(this._terminal.ybase + this._terminal.scrollTop, 0, this._terminal.blankLine());
this._terminal.buffer.lines.splice(this._terminal.ybase + this._terminal.scrollBottom, 1);
this._terminal.buffer.lines.splice(this._terminal.ybase + this._terminal.scrollTop, 0, this._terminal.blankLine());
}
// this.maxRange();
this._terminal.updateRange(this._terminal.scrollTop);
@@ -565,7 +565,7 @@ export class InputHandler implements IInputHandler {
ch = [this._terminal.eraseAttr(), ' ', 1]; // xterm
while (param-- && j < this._terminal.cols) {
this._terminal.lines.get(row)[j++] = ch;
this._terminal.buffer.lines.get(row)[j++] = ch;
}
}
@@ -615,7 +615,7 @@ export class InputHandler implements IInputHandler {
*/
public repeatPrecedingCharacter(params: number[]): void {
let param = params[0] || 1
, line = this._terminal.lines.get(this._terminal.ybase + this._terminal.y)
, line = this._terminal.buffer.lines.get(this._terminal.ybase + this._terminal.y)
, ch = line[this._terminal.x - 1] || [this._terminal.defAttr, ' ', 1];
while (param--) {
@@ -949,7 +949,7 @@ export class InputHandler implements IInputHandler {
case 1047: // alt screen buffer
if (!this._terminal.normal) {
let normal = {
lines: this._terminal.lines,
lines: this._terminal.buffers.normal.lines,
ybase: this._terminal.ybase,
ydisp: this._terminal.ydisp,
x: this._terminal.x,
@@ -1128,7 +1128,7 @@ export class InputHandler implements IInputHandler {
case 47: // normal screen buffer
case 1047: // normal screen buffer - clearing it first
if (this._terminal.normal) {
this._terminal.lines = this._terminal.normal.lines;
this._terminal.buffers.activateNormalBuffer();
this._terminal.ybase = this._terminal.normal.ybase;
this._terminal.ydisp = this._terminal.normal.ydisp;
this._terminal.x = this._terminal.normal.x;
@@ -1138,7 +1138,7 @@ export class InputHandler implements IInputHandler {
this._terminal.tabs = this._terminal.normal.tabs;
this._terminal.normal = null;
// Ensure the selection manager has the correct buffer
this._terminal.selectionManager.setBuffer(this._terminal.lines);
this._terminal.selectionManager.setBuffer(this._terminal.buffer.lines);
// if (params === 1049) {
// this.x = this.savedX;
// this.y = this.savedY;
+1 -1
View File
@@ -141,7 +141,7 @@ export class Renderer {
for (; y <= end; y++) {
let row = y + this._terminal.ydisp;
let line = this._terminal.lines.get(row);
let line = this._terminal.buffer.lines.get(row);
let x;
if (this._terminal.y === y - (this._terminal.ybase - this._terminal.ydisp) &&
+2 -2
View File
@@ -68,9 +68,9 @@ export class Viewport {
* Updates dimensions and synchronizes the scroll area if necessary.
*/
public syncScrollArea(): void {
if (this.lastRecordedBufferLength !== this.terminal.lines.length) {
if (this.lastRecordedBufferLength !== this.terminal.buffer.lines.length) {
// If buffer height changed
this.lastRecordedBufferLength = this.terminal.lines.length;
this.lastRecordedBufferLength = this.terminal.buffer.lines.length;
this.refresh();
} else if (this.lastRecordedViewportHeight !== this.terminal.rows) {
// If viewport height changed
+40 -29
View File
@@ -244,19 +244,25 @@ function Terminal(options) {
// leftover surrogate high from previous write invocation
this.surrogate_high = '';
// Create the terminal's buffers and set the current buffer
this.buffers = new BufferSet(this);
this.buffer = this.buffers.active; // Convenience shortcut;
this.buffers.on('activate', function (buffer) {
this.buffer = buffer;
});
/**
* An array of all lines in the entire buffer, including the prompt. The lines are array of
* characters which are 2-length arrays where [0] is an attribute and [1] is the character.
*/
this.lines = new CircularList(this.scrollback);
var i = this.rows;
while (i--) {
this.lines.push(this.blankLine());
this.buffer.lines.push(this.blankLine());
}
// Ensure the selection manager has the correct buffer
if (this.selectionManager) {
this.selectionManager.setBuffer(this.lines);
this.selectionManager.setBuffer(this.buffer.lines);
}
this.tabs;
@@ -432,17 +438,17 @@ Terminal.prototype.setOption = function(key, value) {
}
if (this.options[key] !== value) {
if (this.lines.length > value) {
const amountToTrim = this.lines.length - value;
if (this.buffer.length > value) {
const amountToTrim = this.buffer.lines.length - value;
const needsRefresh = (this.ydisp - amountToTrim < 0);
this.lines.trimStart(amountToTrim);
this.buffer.lines.trimStart(amountToTrim);
this.ybase = Math.max(this.ybase - amountToTrim, 0);
this.ydisp = Math.max(this.ydisp - amountToTrim, 0);
if (needsRefresh) {
this.refresh(0, this.rows - 1);
}
}
this.lines.maxLength = value;
this.buffer.lines.maxLength = value;
this.viewport.syncScrollArea();
}
break;
@@ -727,6 +733,7 @@ Terminal.prototype.open = function(parent, focus) {
this.viewport = new Viewport(this, this.viewportElement, this.viewportScrollArea, this.charMeasure);
this.renderer = new Renderer(this);
<<<<<<< HEAD
this.selectionManager = new SelectionManager(this, this.lines, this.rowContainer, this.charMeasure);
this.selectionManager.on('refresh', data => {
this.renderer.refreshSelection(data.start, data.end);
@@ -739,6 +746,10 @@ Terminal.prototype.open = function(parent, focus) {
this.textarea.focus();
this.textarea.select();
});
=======
this.selectionManager = new SelectionManager(this, this.buffer.lines, this.rowContainer, this.charMeasure);
this.selectionManager.on('refresh', data => this.renderer.refreshSelection(data.start, data.end));
>>>>>>> Create `terminal.buffer` convenience attribute
this.on('scroll', () => this.selectionManager.refresh());
this.viewportElement.addEventListener('scroll', () => this.selectionManager.refresh());
@@ -1171,8 +1182,8 @@ Terminal.prototype.scroll = function(isWrapped) {
var row;
// Make room for the new row in lines
if (this.lines.length === this.lines.maxLength) {
this.lines.trimStart(1);
if (this.buffer.lines.length === this.buffer.lines.maxLength) {
this.buffer.lines.trimStart(1);
this.ybase--;
if (this.ydisp !== 0) {
this.ydisp--;
@@ -1192,12 +1203,12 @@ Terminal.prototype.scroll = function(isWrapped) {
// subtract the bottom scroll region
row -= this.rows - 1 - this.scrollBottom;
if (row === this.lines.length) {
if (row === this.buffer.lines.length) {
// Optimization: pushing is faster than splicing when they amount to the same behavior
this.lines.push(this.blankLine(undefined, isWrapped));
this.buffer.lines.push(this.blankLine(undefined, isWrapped));
} else {
// add our new line
this.lines.splice(row, 0, this.blankLine(undefined, isWrapped));
this.buffer.lines.splice(row, 0, this.blankLine(undefined, isWrapped));
}
if (this.scrollTop !== 0) {
@@ -1207,7 +1218,7 @@ Terminal.prototype.scroll = function(isWrapped) {
this.ydisp = this.ybase;
}
}
this.lines.splice(this.ybase + this.scrollTop, 1);
this.buffer.lines.splice(this.ybase + this.scrollTop, 1);
}
// this.maxRange();
@@ -1960,10 +1971,10 @@ Terminal.prototype.resize = function(x, y) {
j = this.cols;
if (j < x) {
ch = [this.defAttr, ' ', 1]; // does xterm use the default attr?
i = this.lines.length;
i = this.buffer.lines.length;
while (i--) {
while (this.lines.get(i).length < x) {
this.lines.get(i).push(ch);
while (this.buffer.lines.get(i).length < x) {
this.buffer.lines.get(i).push(ch);
}
}
}
@@ -1978,8 +1989,8 @@ Terminal.prototype.resize = function(x, y) {
el = this.element;
while (j++ < y) {
// y is rows, not this.y
if (this.lines.length < y + this.ybase) {
if (this.ybase > 0 && this.lines.length <= this.ybase + this.y + addToY + 1) {
if (this.buffer.lines.length < y + this.ybase) {
if (this.ybase > 0 && this.buffer.lines.length <= this.ybase + this.y + addToY + 1) {
// There is room above the buffer and there are no empty elements below the line,
// scroll up
this.ybase--;
@@ -1991,7 +2002,7 @@ Terminal.prototype.resize = function(x, y) {
} else {
// Add a blank line if there is no buffer left at the top to scroll to, or if there
// are blank lines after the cursor
this.lines.push(this.blankLine());
this.buffer.lines.push(this.blankLine());
}
}
if (this.children.length < y) {
@@ -2000,10 +2011,10 @@ Terminal.prototype.resize = function(x, y) {
}
} else { // (j > y)
while (j-- > y) {
if (this.lines.length > y + this.ybase) {
if (this.lines.length > this.ybase + this.y + 1) {
if (this.buffer.lines.length > y + this.ybase) {
if (this.buffer.lines.length > this.ybase + this.y + 1) {
// The line is a blank line below the cursor, remove it
this.lines.pop();
this.buffer.lines.pop();
} else {
// The line is the cursor, scroll down
this.ybase++;
@@ -2121,7 +2132,7 @@ Terminal.prototype.nextStop = function(x) {
* @param {number} y The line in which to operate.
*/
Terminal.prototype.eraseRight = function(x, y) {
var line = this.lines.get(this.ybase + y);
var line = this.buffer.lines.get(this.ybase + y);
if (!line) {
return;
}
@@ -2140,7 +2151,7 @@ Terminal.prototype.eraseRight = function(x, y) {
* @param {number} y The line in which to operate.
*/
Terminal.prototype.eraseLeft = function(x, y) {
var line = this.lines.get(this.ybase + y);
var line = this.buffer.lines.get(this.ybase + y);
if (!line) {
return;
}
@@ -2160,13 +2171,13 @@ Terminal.prototype.clear = function() {
// Don't clear if it's already clear
return;
}
this.lines.set(0, this.lines.get(this.ybase + this.y));
this.lines.length = 1;
this.buffer.lines.set(0, this.buffer.lines.get(this.ybase + this.y));
this.buffer.lines.length = 1;
this.ydisp = 0;
this.ybase = 0;
this.y = 0;
for (var i = 1; i < this.rows; i++) {
this.lines.push(this.blankLine());
this.buffer.lines.push(this.blankLine());
}
this.refresh(0, this.rows - 1);
this.emit('scroll', this.ydisp);
@@ -2299,8 +2310,8 @@ Terminal.prototype.reverseIndex = function() {
// possibly move the code below to term.reverseScroll();
// test: echo -ne '\e[1;1H\e[44m\eM\e[0m'
// blankLine(true) is xterm/linux behavior
this.lines.shiftElements(this.y + this.ybase, this.rows - 1, 1);
this.lines.set(this.y + this.ybase, this.blankLine(true));
this.buffer.lines.shiftElements(this.y + this.ybase, this.rows - 1, 1);
this.buffer.lines.set(this.y + this.ybase, this.blankLine(true));
this.updateRange(this.scrollTop);
this.updateRange(this.scrollBottom);
} else {