mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Merge branch 'master' into reuse_bufferlines
This commit is contained in:
@@ -171,6 +171,7 @@ computational environment for Jupyter, supporting interactive data science and s
|
||||
- [**SSH Web Client**](https://github.com/roke22/PHP-SSH2-Web-Client): SSH Web Client with PHP.
|
||||
- [**Shellvault**](https://www.shellvault.io): The cloud-based SSH terminal you can access from anywhere.
|
||||
- [**Juno**](http://junolab.org/): A flexible Julia IDE, based on Atom.
|
||||
- [**webssh**](https://github.com/huashengdun/webssh): Web based ssh client.
|
||||
|
||||
[And much more...](https://github.com/xtermjs/xterm.js/network/dependents)
|
||||
|
||||
|
||||
@@ -438,6 +438,36 @@ describe('InputHandler', () => {
|
||||
termNew.buffer.x = 40;
|
||||
inputHandlerNew.eraseInDisplay([2]);
|
||||
expect(termContent(termNew)).eql(termContent(termOld));
|
||||
|
||||
// reset and add a wrapped line
|
||||
termNew.buffer.y = 0;
|
||||
termNew.buffer.x = 0;
|
||||
inputHandlerNew.parse(Array(termNew.cols + 1).join('a')); // line 0
|
||||
inputHandlerNew.parse(Array(termNew.cols + 10).join('a')); // line 1 and 2
|
||||
for (let i = 3; i < termOld.rows; ++i) inputHandlerNew.parse(Array(termNew.cols + 1).join('a'));
|
||||
|
||||
// params[1] left and above with wrap
|
||||
// confirm precondition that line 2 is wrapped
|
||||
expect(termNew.buffer.lines.get(2).isWrapped).true;
|
||||
termNew.buffer.y = 2;
|
||||
termNew.buffer.x = 40;
|
||||
inputHandlerNew.eraseInDisplay([1]);
|
||||
expect(termNew.buffer.lines.get(2).isWrapped).false;
|
||||
|
||||
// reset and add a wrapped line
|
||||
termNew.buffer.y = 0;
|
||||
termNew.buffer.x = 0;
|
||||
inputHandlerNew.parse(Array(termNew.cols + 1).join('a')); // line 0
|
||||
inputHandlerNew.parse(Array(termNew.cols + 10).join('a')); // line 1 and 2
|
||||
for (let i = 3; i < termOld.rows; ++i) inputHandlerNew.parse(Array(termNew.cols + 1).join('a'));
|
||||
|
||||
// params[1] left and above with wrap
|
||||
// confirm precondition that line 2 is wrapped
|
||||
expect(termNew.buffer.lines.get(2).isWrapped).true;
|
||||
termNew.buffer.y = 1;
|
||||
termNew.buffer.x = 90; // Cursor is beyond last column
|
||||
inputHandlerNew.eraseInDisplay([1]);
|
||||
expect(termNew.buffer.lines.get(2).isWrapped).false;
|
||||
});
|
||||
});
|
||||
it('convertEol setting', function(): void {
|
||||
|
||||
+26
-29
@@ -24,26 +24,6 @@ const GLEVEL: {[key: string]: number} = {'(': 0, ')': 1, '*': 2, '+': 3, '-': 1,
|
||||
* DCS subparser implementations
|
||||
*/
|
||||
|
||||
/**
|
||||
* DCS + q Pt ST (xterm)
|
||||
* Request Terminfo String
|
||||
* not supported
|
||||
*/
|
||||
class RequestTerminfo implements IDcsHandler {
|
||||
private _data: string;
|
||||
constructor(private _terminal: any) { }
|
||||
hook(collect: string, params: number[], flag: number): void {
|
||||
this._data = '';
|
||||
}
|
||||
put(data: string, start: number, end: number): void {
|
||||
this._data += data.substring(start, end);
|
||||
}
|
||||
unhook(): void {
|
||||
// invalid: DCS 0 + r Pt ST
|
||||
this._terminal.handler(`${C0.ESC}P0+r${this._data}${C0.ESC}\\`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DCS $ q Pt ST
|
||||
* DECRQSS (https://vt100.net/docs/vt510-rm/DECRQSS.html)
|
||||
@@ -86,7 +66,7 @@ class DECRQSS implements IDcsHandler {
|
||||
default:
|
||||
// invalid: DCS 0 $ r Pt ST (xterm)
|
||||
this._terminal.error('Unknown DCS $q %s', this._data);
|
||||
this._terminal.handler(`${C0.ESC}P0$r${this._data}${C0.ESC}\\`);
|
||||
this._terminal.handler(`${C0.ESC}P0$r${C0.ESC}\\`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -287,7 +267,6 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
* DCS handler
|
||||
*/
|
||||
this._parser.setDcsHandler('$q', new DECRQSS(this._terminal));
|
||||
this._parser.setDcsHandler('+q', new RequestTerminfo(this._terminal));
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
@@ -722,12 +701,25 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
* @param start first cell index to be erased
|
||||
* @param end end - 1 is last erased cell
|
||||
*/
|
||||
private _eraseInBufferLine(y: number, start: number, end: number): void {
|
||||
this._terminal.buffer.lines.get(this._terminal.buffer.ybase + y).replaceCells(
|
||||
private _eraseInBufferLine(y: number, start: number, end: number, clearWrap: boolean = false): void {
|
||||
const line = this._terminal.buffer.lines.get(this._terminal.buffer.ybase + y);
|
||||
line.replaceCells(
|
||||
start,
|
||||
end,
|
||||
[this._terminal.eraseAttr(), NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]
|
||||
);
|
||||
if (clearWrap) {
|
||||
line.isWrapped = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to reset cells in a terminal row.
|
||||
* The cell gets replaced with the eraseChar of the terminal and the isWrapped property is set to false.
|
||||
* @param y row index
|
||||
*/
|
||||
private _resetBufferLine(y: number): void {
|
||||
this._eraseInBufferLine(y, 0, this._terminal.cols, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -748,18 +740,23 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
case 0:
|
||||
j = this._terminal.buffer.y;
|
||||
this._terminal.updateRange(j);
|
||||
this._eraseInBufferLine(j++, this._terminal.buffer.x, this._terminal.cols);
|
||||
this._eraseInBufferLine(j++, this._terminal.buffer.x, this._terminal.cols, this._terminal.buffer.x === 0);
|
||||
for (; j < this._terminal.rows; j++) {
|
||||
this._eraseInBufferLine(j, 0, this._terminal.cols);
|
||||
this._resetBufferLine(j);
|
||||
}
|
||||
this._terminal.updateRange(j);
|
||||
break;
|
||||
case 1:
|
||||
j = this._terminal.buffer.y;
|
||||
this._terminal.updateRange(j);
|
||||
this._eraseInBufferLine(j, 0, this._terminal.buffer.x + 1);
|
||||
// Deleted front part of line and everything before. This line will no longer be wrapped.
|
||||
this._eraseInBufferLine(j, 0, this._terminal.buffer.x + 1, true);
|
||||
if (this._terminal.buffer.x + 1 >= this._terminal.cols) {
|
||||
// Deleted entire previous line. This next line can no longer be wrapped.
|
||||
this._terminal.buffer.lines.get(j + 1).isWrapped = false;
|
||||
}
|
||||
while (j--) {
|
||||
this._eraseInBufferLine(j, 0, this._terminal.cols);
|
||||
this._resetBufferLine(j);
|
||||
}
|
||||
this._terminal.updateRange(0);
|
||||
break;
|
||||
@@ -767,7 +764,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
j = this._terminal.rows;
|
||||
this._terminal.updateRange(j - 1);
|
||||
while (j--) {
|
||||
this._eraseInBufferLine(j, 0, this._terminal.cols);
|
||||
this._resetBufferLine(j);
|
||||
}
|
||||
this._terminal.updateRange(0);
|
||||
break;
|
||||
|
||||
+5
-1
@@ -346,7 +346,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
|
||||
}
|
||||
|
||||
public get isFocused(): boolean {
|
||||
return document.activeElement === this.textarea;
|
||||
return document.activeElement === this.textarea && document.hasFocus();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1179,6 +1179,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
|
||||
* @param isWrapped Whether the new line is wrapped from the previous line.
|
||||
*/
|
||||
public scroll(isWrapped?: boolean): void {
|
||||
<<<<<<< HEAD
|
||||
let newLine: IBufferLine;
|
||||
const useRecycling = this.options.experimentalPushRecycling;
|
||||
if (useRecycling) {
|
||||
@@ -1192,6 +1193,9 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II
|
||||
newLine = this.buffer.getBlankLine(DEFAULT_ATTR, isWrapped);
|
||||
}
|
||||
|
||||
=======
|
||||
const newLine = this.buffer.getBlankLine(this.eraseAttr(), isWrapped);
|
||||
>>>>>>> master
|
||||
const topRow = this.buffer.ybase + this.buffer.scrollTop;
|
||||
const bottomRow = this.buffer.ybase + this.buffer.scrollBottom;
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@ export class SearchHelper implements ISearchHelper {
|
||||
do {
|
||||
const nextLine = this._terminal._core.buffer.lines.get(lineIndex + 1);
|
||||
lineWrapsToNext = nextLine ? nextLine.isWrapped : false;
|
||||
lineString += this._terminal._core.buffer.translateBufferLineToString(lineIndex, !lineWrapsToNext && trimRight);
|
||||
lineString += this._terminal._core.buffer.translateBufferLineToString(lineIndex, !lineWrapsToNext && trimRight).substring(0, this._terminal.cols);
|
||||
lineIndex++;
|
||||
} while (lineWrapsToNext);
|
||||
|
||||
|
||||
@@ -81,6 +81,9 @@ describe('search addon', () => {
|
||||
expect(hello3).eql(undefined);
|
||||
expect(llo).eql(undefined);
|
||||
expect(goodbye).eql({col: 0, row: 5, term: 'goodbye'});
|
||||
term.core.resize(9, 5);
|
||||
const hello0Resize = term.searchHelper.findInLine('Hello', 0);
|
||||
expect(hello0Resize).eql({col: 8, row: 0, term: 'Hello'});
|
||||
});
|
||||
it('should respect search regex', () => {
|
||||
search.apply(<any>MockTerminal);
|
||||
|
||||
@@ -352,7 +352,11 @@ export class DomRenderer extends EventEmitter implements IRenderer {
|
||||
|
||||
private _setCellUnderline(x: number, x2: number, y: number, y2: number, cols: number, enabled: boolean): void {
|
||||
while (x !== x2 || y !== y2) {
|
||||
const span = <HTMLElement>this._rowElements[y].children[x];
|
||||
const row = this._rowElements[y];
|
||||
if (!row) {
|
||||
return;
|
||||
}
|
||||
const span = <HTMLElement>row.children[x];
|
||||
span.style.textDecoration = enabled ? 'underline' : 'none';
|
||||
x = (x + 1) % cols;
|
||||
if (x === 0) {
|
||||
|
||||
Reference in New Issue
Block a user