Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

xterm

Package Overview
Dependencies
Maintainers
2
Versions
1092
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

xterm - npm Package Compare versions

Comparing version 3.9.1 to 3.10.0-beta2

lib/common/Clone.js

1

lib/addons/fullscreen/fullscreen.js

@@ -15,2 +15,3 @@ "use strict";

}
fn = fn.bind(term.element.classList);
fn('fullscreen');

@@ -17,0 +18,0 @@ }

@@ -18,2 +18,3 @@ import { Terminal } from 'xterm';

caseSensitive?: boolean;
incremental?: boolean;
}

@@ -20,0 +21,0 @@ export interface ISearchResult {

import { ISearchHelper, ISearchAddonTerminal, ISearchOptions, ISearchResult } from './Interfaces';
export declare class SearchHelper implements ISearchHelper {
private _terminal;
private _linesCache;
private _linesCacheTimeoutId;
constructor(_terminal: ISearchAddonTerminal);
findNext(term: string, searchOptions?: ISearchOptions): boolean;
findPrevious(term: string, searchOptions?: ISearchOptions): boolean;
private _initLinesCache;
private _destroyLinesCache;
private _isWholeWord;
protected _findInLine(term: string, y: number, searchOptions?: ISearchOptions): ISearchResult;
protected _findInLine(term: string, row: number, col: number, searchOptions?: ISearchOptions, isReverseSearch?: boolean): ISearchResult;
translateBufferLineToStringWithWrap(lineIndex: number, trimRight: boolean): string;
private _selectResult;
}

148

lib/addons/search/SearchHelper.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var nonWordCharacters = ' ~!@#$%^&*()+`-=[]{}|\;:"\',./<>?';
var NON_WORD_CHARACTERS = ' ~!@#$%^&*()+`-=[]{}|\;:"\',./<>?';
var LINES_CACHE_TIME_TO_LIVE = 15 * 1000;
var SearchHelper = (function () {
function SearchHelper(_terminal) {
this._terminal = _terminal;
this._linesCache = null;
this._linesCacheTimeoutId = 0;
this._destroyLinesCache = this._destroyLinesCache.bind(this);
}
SearchHelper.prototype.findNext = function (term, searchOptions) {
var selectionManager = this._terminal._core.selectionManager;
var incremental = searchOptions.incremental;
var result;
if (!term || term.length === 0) {
selectionManager.clearSelection();
return false;
}
var result;
var startCol = 0;
var startRow = this._terminal._core.buffer.ydisp;
if (this._terminal._core.selectionManager.selectionEnd) {
if (selectionManager.selectionEnd) {
if (this._terminal.getSelection().length !== 0) {
startRow = this._terminal._core.selectionManager.selectionEnd[1];
startRow = incremental ? selectionManager.selectionStart[1] : selectionManager.selectionEnd[1];
startCol = incremental ? selectionManager.selectionStart[0] : selectionManager.selectionEnd[0];
}
}
for (var y = startRow + 1; y < this._terminal._core.buffer.ybase + this._terminal.rows; y++) {
result = this._findInLine(term, y, searchOptions);
if (result) {
break;
this._initLinesCache();
result = this._findInLine(term, startRow, startCol, searchOptions);
if (!result) {
for (var y = startRow + 1; y < this._terminal._core.buffer.ybase + this._terminal.rows; y++) {
result = this._findInLine(term, y, 0, searchOptions);
if (result) {
break;
}
}
}
if (!result) {
for (var y = 0; y < startRow; y++) {
result = this._findInLine(term, y, searchOptions);
for (var y = 0; y <= startRow; y++) {
result = this._findInLine(term, y, 0, searchOptions);
if (result) {

@@ -36,21 +49,31 @@ break;

SearchHelper.prototype.findPrevious = function (term, searchOptions) {
var selectionManager = this._terminal._core.selectionManager;
var result;
if (!term || term.length === 0) {
selectionManager.clearSelection();
return false;
}
var result;
var isReverseSearch = true;
var startRow = this._terminal._core.buffer.ydisp;
if (this._terminal._core.selectionManager.selectionStart) {
var startCol = this._terminal._core.buffer.lines.get(startRow).length;
if (selectionManager.selectionStart) {
if (this._terminal.getSelection().length !== 0) {
startRow = this._terminal._core.selectionManager.selectionStart[1];
startRow = selectionManager.selectionStart[1];
startCol = selectionManager.selectionStart[0];
}
}
for (var y = startRow - 1; y >= 0; y--) {
result = this._findInLine(term, y, searchOptions);
if (result) {
break;
this._initLinesCache();
result = this._findInLine(term, startRow, startCol, searchOptions, isReverseSearch);
if (!result) {
for (var y = startRow - 1; y >= 0; y--) {
result = this._findInLine(term, y, this._terminal._core.buffer.lines.get(y).length, searchOptions, isReverseSearch);
if (result) {
break;
}
}
}
if (!result) {
for (var y = this._terminal._core.buffer.ybase + this._terminal.rows - 1; y > startRow; y--) {
result = this._findInLine(term, y, searchOptions);
var searchFrom = this._terminal._core.buffer.ybase + this._terminal.rows - 1;
for (var y = searchFrom; y >= startRow; y--) {
result = this._findInLine(term, y, this._terminal._core.buffer.lines.get(y).length, searchOptions, isReverseSearch);
if (result) {

@@ -63,44 +86,85 @@ break;

};
SearchHelper.prototype._initLinesCache = function () {
var _this = this;
if (!this._linesCache) {
this._linesCache = new Array(this._terminal._core.buffer.length);
this._terminal.on('cursormove', this._destroyLinesCache);
}
window.clearTimeout(this._linesCacheTimeoutId);
this._linesCacheTimeoutId = window.setTimeout(function () { return _this._destroyLinesCache(); }, LINES_CACHE_TIME_TO_LIVE);
};
SearchHelper.prototype._destroyLinesCache = function () {
this._linesCache = null;
this._terminal.off('cursormove', this._destroyLinesCache);
if (this._linesCacheTimeoutId) {
window.clearTimeout(this._linesCacheTimeoutId);
this._linesCacheTimeoutId = 0;
}
};
SearchHelper.prototype._isWholeWord = function (searchIndex, line, term) {
return (((searchIndex === 0) || (nonWordCharacters.indexOf(line[searchIndex - 1]) !== -1)) &&
(((searchIndex + term.length) === line.length) || (nonWordCharacters.indexOf(line[searchIndex + term.length]) !== -1)));
return (((searchIndex === 0) || (NON_WORD_CHARACTERS.indexOf(line[searchIndex - 1]) !== -1)) &&
(((searchIndex + term.length) === line.length) || (NON_WORD_CHARACTERS.indexOf(line[searchIndex + term.length]) !== -1)));
};
SearchHelper.prototype._findInLine = function (term, y, searchOptions) {
SearchHelper.prototype._findInLine = function (term, row, col, searchOptions, isReverseSearch) {
if (searchOptions === void 0) { searchOptions = {}; }
if (this._terminal._core.buffer.lines.get(y).isWrapped) {
if (isReverseSearch === void 0) { isReverseSearch = false; }
if (this._terminal._core.buffer.lines.get(row).isWrapped) {
return;
}
var stringLine = this.translateBufferLineToStringWithWrap(y, true);
var stringLine = this._linesCache ? this._linesCache[row] : void 0;
if (stringLine === void 0) {
stringLine = this.translateBufferLineToStringWithWrap(row, true);
if (this._linesCache) {
this._linesCache[row] = stringLine;
}
}
var searchTerm = searchOptions.caseSensitive ? term : term.toLowerCase();
var searchStringLine = searchOptions.caseSensitive ? stringLine : stringLine.toLowerCase();
var searchTerm = searchOptions.caseSensitive ? term : term.toLowerCase();
var searchIndex = -1;
var resultIndex = -1;
if (searchOptions.regex) {
var searchRegex = RegExp(searchTerm, 'g');
var foundTerm = searchRegex.exec(searchStringLine);
if (foundTerm && foundTerm[0].length > 0) {
searchIndex = searchRegex.lastIndex - foundTerm[0].length;
term = foundTerm[0];
var foundTerm = void 0;
if (isReverseSearch) {
while (foundTerm = searchRegex.exec(searchStringLine.slice(0, col))) {
resultIndex = searchRegex.lastIndex - foundTerm[0].length;
term = foundTerm[0];
searchRegex.lastIndex -= (term.length - 1);
}
}
else {
foundTerm = searchRegex.exec(searchStringLine.slice(col));
if (foundTerm && foundTerm[0].length > 0) {
resultIndex = col + (searchRegex.lastIndex - foundTerm[0].length);
term = foundTerm[0];
}
}
}
else {
searchIndex = searchStringLine.indexOf(searchTerm);
if (isReverseSearch) {
if (col - searchTerm.length >= 0) {
resultIndex = searchStringLine.lastIndexOf(searchTerm, col - searchTerm.length);
}
}
else {
resultIndex = searchStringLine.indexOf(searchTerm, col);
}
}
if (searchIndex >= 0) {
if (searchIndex >= this._terminal.cols) {
y += Math.floor(searchIndex / this._terminal.cols);
searchIndex = searchIndex % this._terminal.cols;
if (resultIndex >= 0) {
if (resultIndex >= this._terminal.cols) {
row += Math.floor(resultIndex / this._terminal.cols);
resultIndex = resultIndex % this._terminal.cols;
}
if (searchOptions.wholeWord && !this._isWholeWord(searchIndex, searchStringLine, term)) {
if (searchOptions.wholeWord && !this._isWholeWord(resultIndex, searchStringLine, term)) {
return;
}
var line = this._terminal._core.buffer.lines.get(y);
for (var i = 0; i < searchIndex; i++) {
var line = this._terminal._core.buffer.lines.get(row);
for (var i = 0; i < resultIndex; i++) {
var charData = line.get(i);
var char = charData[1];
if (char.length > 1) {
searchIndex -= char.length - 1;
resultIndex -= char.length - 1;
}
var charWidth = charData[2];
if (charWidth === 0) {
searchIndex++;
resultIndex++;
}

@@ -110,4 +174,4 @@ }

term: term,
col: searchIndex,
row: y
col: resultIndex,
row: row
};

@@ -114,0 +178,0 @@ }

@@ -12,3 +12,3 @@ "use strict";

var hostClause = '((' + domainBodyClause + '\\.' + tldClause + ')|' + ipClause + '|' + localHostClause + ')' + portClause + '?';
var pathClause = '(\\/[\\/\\w\\.\\-%~:]*)*([^:\\s])';
var pathClause = '(\\/[\\/\\w\\.\\-%~:]*)*([^:"\'\\s])';
var queryStringHashFragmentCharacterSet = '[0-9\\w\\[\\]\\(\\)\\/\\?\\!#@$%&\'*+,:;~\\=\\.\\-]*';

@@ -15,0 +15,0 @@ var queryStringClause = '(\\?' + queryStringHashFragmentCharacterSet + ')?';

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var CHAR_DATA_CODE_INDEX = 3;
var NULL_CELL_CODE = 32;
var NULL_CELL_CODE = 0;
var WHITESPACE_CELL_CODE = 32;
function winptyCompatInit(terminal) {

@@ -14,3 +15,3 @@ var addonTerminal = terminal;

var lastChar = line.get(addonTerminal.cols - 1);
if (lastChar[CHAR_DATA_CODE_INDEX] !== NULL_CELL_CODE) {
if (lastChar[CHAR_DATA_CODE_INDEX] !== NULL_CELL_CODE && lastChar[CHAR_DATA_CODE_INDEX] !== WHITESPACE_CELL_CODE) {
var nextLine = addonTerminal._core.buffer.lines.get(addonTerminal._core.buffer.ybase + addonTerminal._core.buffer.y);

@@ -17,0 +18,0 @@ nextLine.isWrapped = true;

@@ -26,5 +26,8 @@ "use strict";

exports.MAX_BUFFER_SIZE = 4294967295;
exports.NULL_CELL_CHAR = ' ';
exports.NULL_CELL_CHAR = '';
exports.NULL_CELL_WIDTH = 1;
exports.NULL_CELL_CODE = 32;
exports.NULL_CELL_CODE = 0;
exports.WHITESPACE_CELL_CHAR = ' ';
exports.WHITESPACE_CELL_WIDTH = 1;
exports.WHITESPACE_CELL_CODE = 32;
var Buffer = (function () {

@@ -179,3 +182,3 @@ function Buffer(_terminal, _hasScrollback) {

if (!line) {
[-1, -1];
return [-1, -1];
}

@@ -194,4 +197,2 @@ for (var i = 0; i < line.length; ++i) {

if (startCol === void 0) { startCol = 0; }
if (endCol === void 0) { endCol = null; }
var lineString = '';
var line = this.lines.get(lineIndex);

@@ -201,39 +202,3 @@ if (!line) {

}
var startIndex = startCol;
if (endCol === null) {
endCol = line.length;
}
var endIndex = endCol;
for (var i = 0; i < line.length; i++) {
var char = line.get(i);
lineString += char[exports.CHAR_DATA_CHAR_INDEX];
if (char[exports.CHAR_DATA_WIDTH_INDEX] === 0) {
if (startCol >= i) {
startIndex--;
}
if (endCol > i) {
endIndex--;
}
}
else {
if (char[exports.CHAR_DATA_CHAR_INDEX].length > 1) {
if (startCol > i) {
startIndex += char[exports.CHAR_DATA_CHAR_INDEX].length - 1;
}
if (endCol > i) {
endIndex += char[exports.CHAR_DATA_CHAR_INDEX].length - 1;
}
}
}
}
if (trimRight) {
var rightWhitespaceIndex = lineString.search(/\s+$/);
if (rightWhitespaceIndex !== -1) {
endIndex = Math.min(endIndex, rightWhitespaceIndex);
}
if (endIndex <= startIndex) {
return '';
}
}
return lineString.substring(startIndex, endIndex);
return line.translateToString(trimRight, startCol, endCol);
};

@@ -364,3 +329,3 @@ Buffer.prototype.getWrappedRangeForLine = function (y) {

for (var i = range.first; i <= range.last; ++i) {
result += this._buffer.translateBufferLineToString(i, (this._trimRight) ? i === range.last : false);
result += this._buffer.translateBufferLineToString(i, this._trimRight);
}

@@ -367,0 +332,0 @@ this._current = range.last + 1;

@@ -88,2 +88,25 @@ "use strict";

};
BufferLineJSArray.prototype.getTrimmedLength = function () {
for (var i = this.length - 1; i >= 0; --i) {
var ch = this.get(i);
if (ch[Buffer_1.CHAR_DATA_CHAR_INDEX] !== '') {
return i + ch[Buffer_1.CHAR_DATA_WIDTH_INDEX];
}
}
return 0;
};
BufferLineJSArray.prototype.translateToString = function (trimRight, startCol, endCol) {
if (trimRight === void 0) { trimRight = false; }
if (startCol === void 0) { startCol = 0; }
if (endCol === void 0) { endCol = this.length; }
if (trimRight) {
endCol = Math.min(endCol, this.getTrimmedLength());
}
var result = '';
while (startCol < endCol) {
result += this.get(startCol)[Buffer_1.CHAR_DATA_CHAR_INDEX] || Buffer_1.WHITESPACE_CELL_CHAR;
startCol += this.get(startCol)[Buffer_1.CHAR_DATA_WIDTH_INDEX] || 1;
}
return result;
};
return BufferLineJSArray;

@@ -93,2 +116,3 @@ }());

var CELL_SIZE = 3;
var IS_COMBINED_BIT_MASK = 0x80000000;
var BufferLine = (function () {

@@ -115,7 +139,7 @@ function BufferLine(cols, fillCharData, isWrapped) {

this._data[index * CELL_SIZE + 0],
(stringData & 0x80000000)
(stringData & IS_COMBINED_BIT_MASK)
? this._combined[index]
: (stringData) ? String.fromCharCode(stringData) : '',
this._data[index * CELL_SIZE + 2],
(stringData & 0x80000000)
(stringData & IS_COMBINED_BIT_MASK)
? this._combined[index].charCodeAt(this._combined[index].length - 1)

@@ -129,3 +153,3 @@ : stringData

this._combined[index] = value[1];
this._data[index * CELL_SIZE + 1] = index | 0x80000000;
this._data[index * CELL_SIZE + 1] = index | IS_COMBINED_BIT_MASK;
}

@@ -236,2 +260,25 @@ else {

};
BufferLine.prototype.getTrimmedLength = function () {
for (var i = this.length - 1; i >= 0; --i) {
if (this._data[i * CELL_SIZE + 1] !== 0) {
return i + this._data[i * CELL_SIZE + 2];
}
}
return 0;
};
BufferLine.prototype.translateToString = function (trimRight, startCol, endCol) {
if (trimRight === void 0) { trimRight = false; }
if (startCol === void 0) { startCol = 0; }
if (endCol === void 0) { endCol = this.length; }
if (trimRight) {
endCol = Math.min(endCol, this.getTrimmedLength());
}
var result = '';
while (startCol < endCol) {
var stringData = this._data[startCol * CELL_SIZE + 1];
result += (stringData & IS_COMBINED_BIT_MASK) ? this._combined[startCol] : (stringData) ? String.fromCharCode(stringData) : Buffer_1.WHITESPACE_CELL_CHAR;
startCol += this._data[startCol * CELL_SIZE + 2] || 1;
}
return result;
};
return BufferLine;

@@ -238,0 +285,0 @@ }());

@@ -339,2 +339,6 @@ "use strict";

}
else if (ev.key && !ev.ctrlKey && !ev.altKey && !ev.metaKey &&
ev.keyCode >= 48 && ev.keyCode !== 144 && ev.keyCode !== 145) {
result.key = ev.key;
}
break;

@@ -341,0 +345,0 @@ }

@@ -46,3 +46,3 @@ "use strict";

EXECUTABLES.push.apply(EXECUTABLES, r(0x1c, 0x20));
var DEFAULT_TRANSITION = 1 << 4 | 0;
var NON_ASCII_PRINTABLE = 0xA0;
exports.VT500_TRANSITION_TABLE = (function () {

@@ -53,3 +53,3 @@ var table = new TransitionTable(4095);

for (state in states) {
for (var code = 0; code < 160; ++code) {
for (var code = 0; code <= NON_ASCII_PRINTABLE; ++code) {
table.add(code, state, 1, 0);

@@ -148,2 +148,3 @@ }

table.addMany([0x1b, 0x9c], 13, 14, 0);
table.add(NON_ASCII_PRINTABLE, 8, 5, 8);
return table;

@@ -302,3 +303,3 @@ })();

}
transition = (code < 0xa0) ? (table[currentState << 8 | code]) : DEFAULT_TRANSITION;
transition = table[currentState << 8 | (code < 0xa0 ? code : NON_ASCII_PRINTABLE)];
switch (transition >> 4) {

@@ -335,6 +336,2 @@ case 2:

break;
case 8:
osc += String.fromCharCode(code);
transition |= 8;
break;
case 6:

@@ -438,3 +435,11 @@ transition |= 6;

case 5:
osc += data.charAt(i);
for (var j = i + 1;; j++) {
if (j >= l
|| (code = data.charCodeAt(j)) < 0x20
|| (code > 0x7f && code <= 0x9f)) {
osc += data.substring(i, j);
i = j - 1;
break;
}
}
break;

@@ -441,0 +446,0 @@ case 6:

@@ -131,3 +131,9 @@ "use strict";

rex.lastIndex = stringIndex + uri.length;
if (stringIndex < 0) {
return "break";
}
var bufferIndex = this_1._terminal.buffer.stringIndexToBufferIndex(rowIndex, stringIndex);
if (bufferIndex[0] < 0) {
return "break";
}
var line = this_1._terminal.buffer.lines.get(bufferIndex[0]);

@@ -134,0 +140,0 @@ var char = line.get(bufferIndex[1]);

@@ -23,2 +23,3 @@ "use strict";

if (entry.ownedBy.length === 1) {
entry.atlas.dispose();
charAtlasCache.splice(i, 1);

@@ -53,2 +54,3 @@ }

if (charAtlasCache[i].ownedBy.length === 1) {
charAtlasCache[i].atlas.dispose();
charAtlasCache.splice(i, 1);

@@ -55,0 +57,0 @@ }

@@ -28,3 +28,3 @@ "use strict";

var charData = lineData.get(x);
var char = charData[Buffer_1.CHAR_DATA_CHAR_INDEX];
var char = charData[Buffer_1.CHAR_DATA_CHAR_INDEX] || Buffer_1.WHITESPACE_CELL_CHAR;
var attr = charData[Buffer_1.CHAR_DATA_ATTR_INDEX];

@@ -31,0 +31,0 @@ var width = charData[Buffer_1.CHAR_DATA_WIDTH_INDEX];

@@ -52,4 +52,4 @@ "use strict";

var charData = line.get(x);
var code = charData[Buffer_1.CHAR_DATA_CODE_INDEX];
var chars = charData[Buffer_1.CHAR_DATA_CHAR_INDEX];
var code = charData[Buffer_1.CHAR_DATA_CODE_INDEX] || Buffer_1.WHITESPACE_CELL_CODE;
var chars = charData[Buffer_1.CHAR_DATA_CHAR_INDEX] || Buffer_1.WHITESPACE_CELL_CHAR;
var attr = charData[Buffer_1.CHAR_DATA_ATTR_INDEX];

@@ -56,0 +56,0 @@ var width = charData[Buffer_1.CHAR_DATA_WIDTH_INDEX];

@@ -16,3 +16,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var MouseHelper_1 = require("./utils/MouseHelper");
var MouseHelper_1 = require("./ui/MouseHelper");
var Browser = require("./core/Platform");

@@ -113,3 +113,3 @@ var EventEmitter_1 = require("./common/EventEmitter");

else {
var startRowEndCol = start[1] === end[1] ? end[0] : null;
var startRowEndCol = start[1] === end[1] ? end[0] : undefined;
result.push(this._buffer.translateBufferLineToString(start[1], true, start[0], startRowEndCol));

@@ -116,0 +116,0 @@ for (var i = start[1] + 1; i <= end[1] - 1; i++) {

@@ -68,3 +68,3 @@ "use strict";

for (var cell = 0; cell < term.cols; ++cell) {
lineText += term.buffer.lines.get(line).get(cell)[Buffer_1.CHAR_DATA_CHAR_INDEX];
lineText += term.buffer.lines.get(line).get(cell)[Buffer_1.CHAR_DATA_CHAR_INDEX] || Buffer_1.WHITESPACE_CELL_CHAR;
}

@@ -71,0 +71,0 @@ lineText = lineText.replace(/\s+$/, '');

@@ -31,4 +31,3 @@ "use strict";

var Strings = require("./Strings");
var MouseHelper_1 = require("./utils/MouseHelper");
var Clone_1 = require("./utils/Clone");
var MouseHelper_1 = require("./ui/MouseHelper");
var SoundManager_1 = require("./SoundManager");

@@ -42,2 +41,3 @@ var ColorManager_1 = require("./renderer/ColorManager");

var Keyboard_1 = require("./core/input/Keyboard");
var Clone_1 = require("./common/Clone");
var document = (typeof window !== 'undefined') ? window.document : null;

@@ -274,2 +274,3 @@ var WRITE_BUFFER_PAUSE_THRESHOLD = 5;

}
break;
case 'rendererType':

@@ -276,0 +277,0 @@ if (this.renderer) {

{
"name": "xterm",
"description": "Full xterm terminal, in your browser",
"version": "3.9.1",
"version": "3.10.0-beta2",
"main": "lib/public/Terminal.js",

@@ -31,3 +31,2 @@ "types": "typings/xterm.d.ts",

"gulp-util": "3.0.8",
"jsdoc": "3.4.3",
"jsdom": "^11.11.0",

@@ -39,3 +38,3 @@ "merge-stream": "^1.0.1",

"sorcery": "^0.10.0",
"source-map-loader": "^0.2.3",
"source-map-loader": "^0.2.4",
"ts-loader": "^4.5.0",

@@ -53,2 +52,3 @@ "tslint": "^5.9.1",

"start": "node demo/start",
"start-debug": "node --inspect-brk demo/start",
"start-zmodem": "node demo/zmodem/app",

@@ -63,3 +63,2 @@ "lint": "tslint 'src/**/*.ts' './demo/**/*.ts'",

"mocha": "gulp test",
"build:docs": "jsdoc -c jsdoc.json",
"tsc": "tsc",

@@ -66,0 +65,0 @@ "prebuild": "concurrently --kill-others-on-fail --names \"lib,attach,fit,fullscreen,search,terminado,webLinks,winptyCompat,zmodem,css\" \"tsc\" \"tsc -p ./src/addons/attach\" \"tsc -p ./src/addons/fit\" \"tsc -p ./src/addons/fullscreen\" \"tsc -p ./src/addons/search\" \"tsc -p ./src/addons/terminado\" \"tsc -p ./src/addons/webLinks\" \"tsc -p ./src/addons/winptyCompat\" \"tsc -p ./src/addons/zmodem\" \"gulp css\"",

@@ -5,19 +5,16 @@ # [![xterm.js logo](logo-full.png)](https://xtermjs.org)

[![Coverage Status](https://coveralls.io/repos/github/xtermjs/xterm.js/badge.svg?branch=master)](https://coveralls.io/github/xtermjs/xterm.js?branch=master)
[![Gitter](https://badges.gitter.im/sourcelair/xterm.js.svg)](https://gitter.im/sourcelair/xterm.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![jsDelivr Hits](https://data.jsdelivr.com/v1/package/npm/xterm/badge?style=rounded)](https://www.jsdelivr.com/package/npm/xterm)
Xterm.js is a terminal front-end component written in JavaScript that works in the browser.
Xterm.js is a front-end component written in TypeScript that lets applications bring fully-featured terminals to their users in the browser. It's used by popular projects such as VS Code, Hyper and Theia.
It enables applications to provide fully featured terminals to their users and create great development experiences.
## Features
- **Text-based application support**: Use xterm.js to work with applications like `bash`, `git` etc.
- **Curses-based application support**: Use xterm.js to work with applications like `vim`, `tmux` etc.
- **Mouse events support**: Xterm.js captures mouse events like click and scroll and passes them to the terminal's back-end controlling process
- **CJK (Chinese, Japanese, Korean) character support**: Xterm.js renders CJK characters seamlessly
- **IME support**: Insert international (including CJK) characters using IME input with your keyboard
- **Self-contained library**: Xterm.js works on its own. It does not require any external libraries like jQuery or React to work
- **Modular, event-based API**: Lets you build addons and themes with ease
- **Terminal apps just work**: Xterm.js works with most terminal apps such as `bash`, `vim` and `tmux`, this includes support for curses-based apps and mouse event support
- **Perfomant**: Xterm.js is *really* fast, it even includes a GPU-accelerated renderer
- **Rich unicode support**: Supports CJK, emojis and IMEs
- **Self-contained**: Requires zero dependencies to work
- **Accessible**: Screen reader support can be turned on using the `screenReaderMode` option
- **And much more**: Links, theming, addons, well documented API, etc.
## What xterm.js is not
- Xterm.js is not a terminal application that you can download and use on your computer

@@ -34,3 +31,3 @@ - Xterm.js is not `bash`. Xterm.js can be connected to processes like `bash` and let you interact with them (provide input, receive output)

To start using xterm.js on your browser, add the `xterm.js` and `xterm.css` to the head of your html page. Then create a `<div id="terminal"></div>` onto which xterm can attach itself.
To start using xterm.js on your browser, add the `xterm.js` and `xterm.css` to the head of your html page. Then create a `<div id="terminal"></div>` onto which xterm can attach itself. Finally instantiate the `Terminal` object and then call the `open` function with the DOM object of the `div`.

@@ -55,7 +52,5 @@ ```html

Finally instantiate the `Terminal` object and then call the `open` function with the DOM object of the `div`.
### Importing
The proposed way to load xterm.js is via the ES6 module syntax.
The recommended way to load xterm.js is via the ES6 module syntax:

@@ -66,11 +61,5 @@ ```javascript

### API
The full API for xterm.js is contained within the [TypeScript declaration file](https://github.com/xtermjs/xterm.js/blob/master/typings/xterm.d.ts), use the branch/tag picker in GitHub (`w`) to navigate to the correct version of the API.
Note that some APIs are marked *experimental*, these are added so we can experiment with new ideas without committing to support it like a normal semver API. Note that these APIs can change radically between versions so be sure to read release notes if you plan on using experimental APIs.
### Addons
Addons are JavaScript modules that extend the `Terminal` prototype with new methods and attributes to provide additional functionality. There are a handful available in the main repository in the `src/addons` directory and you can even write your own, by using xterm.js' public API.
Addons are JavaScript modules that extend the `Terminal` prototype with new methods and attributes to provide additional functionality. There are a handful available in the main repository in the `src/addons` directory and you can even write your own by using the [public API](https://github.com/xtermjs/xterm.js/blob/master/typings/xterm.d.ts).

@@ -80,6 +69,5 @@ To use an addon, just import the JavaScript module and pass it to `Terminal`'s `applyAddon` method:

```javascript
import { Terminal } from xterm;
import { Terminal } from 'xterm';
import * as fit from 'xterm/lib/addons/fit/fit';
Terminal.applyAddon(fit);

@@ -95,6 +83,4 @@

There are currently no typings for addons if they are accessed via extending Terminal prototype, so you will need to upcast if using TypeScript, eg. `(<any>xterm).fit()`.
There are currently no typings for addons if they are accessed via extending Terminal prototype, so you will need to upcast if using TypeScript, eg. `(xterm as any).fit()`. Alternatively, you can import the addon function and enhance the terminal on demand. This has better typing support and is friendly to treeshaking.
Alternatively, you can import addon function and enhance the terminal on demand. This would have better typing support and is friendly to treeshaking. E.g.:
```typescript

@@ -105,12 +91,5 @@ import { Terminal } from 'xterm';

// Fit the terminal when necessary:
fit(xterm);
fit(xterm); // Fit the terminal when necessary
```
#### Third party addons
There are also the following third party addons available:
- [xterm-webfont](https://www.npmjs.com/package/xterm-webfont)
## Browser Support

@@ -126,8 +105,10 @@

Xterm.js works seamlessly in Electron apps and may even work on earlier versions of the browsers but these are the browsers we strive to keep working.
Xterm.js works seamlessly in [Electron](https://electronjs.org/) apps and may even work on earlier versions of the browsers, these are the versions we strive to keep working.
## API
The current full API documentation is available in the [TypeScript declaration file on the repository](https://github.com/xtermjs/xterm.js/blob/master/typings/xterm.d.ts), switch the tag (press `w` when viewing the file) to point at the specific version tag you're using.
The full API for xterm.js is contained within the [TypeScript declaration file](https://github.com/xtermjs/xterm.js/blob/master/typings/xterm.d.ts), use the branch/tag picker in GitHub (`w`) to navigate to the correct version of the API.
Note that some APIs are marked *experimental*, these are added to enable experimentation with new ideas without committing to support it like a normal [semver](https://semver.org/) API. Note that these APIs can change radically between versions so be sure to read release notes if you plan on using experimental APIs.
## Real-world uses

@@ -193,3 +174,3 @@ Xterm.js is used in several world-class applications to provide great terminal experiences.

The existing releases are available at this GitHub repo's [Releases](https://github.com/sourcelair/xterm.js/releases), while the roadmap is available as [Milestones](https://github.com/sourcelair/xterm.js/milestones).
All current and past releases are available on this repo's [Releases page](https://github.com/sourcelair/xterm.js/releases), while a rough roadmap is available by looking through [Milestones](https://github.com/sourcelair/xterm.js/milestones).

@@ -196,0 +177,0 @@ ## Contributing

@@ -25,2 +25,3 @@ /**

fn = fn.bind(term.element.classList);
fn('fullscreen');

@@ -27,0 +28,0 @@ }

@@ -28,2 +28,7 @@ /**

caseSensitive?: boolean;
/**
* Use this when you want the selection to expand if it still matches as the
* user types. Note that this only affects findNext.
*/
incremental?: boolean;
}

@@ -30,0 +35,0 @@

@@ -7,4 +7,6 @@ /**

import { ISearchHelper, ISearchAddonTerminal, ISearchOptions, ISearchResult } from './Interfaces';
const nonWordCharacters = ' ~!@#$%^&*()+`-=[]{}|\;:"\',./<>?';
const NON_WORD_CHARACTERS = ' ~!@#$%^&*()+`-=[]{}|\;:"\',./<>?';
const LINES_CACHE_TIME_TO_LIVE = 15 * 1000; // 15 secs
/**

@@ -14,6 +16,12 @@ * A class that knows how to search the terminal and how to display the results.

export class SearchHelper implements ISearchHelper {
/**
* translateBufferLineToStringWithWrap is a fairly expensive call.
* We memoize the calls into an array that has a time based ttl.
* _linesCache is also invalidated when the terminal cursor moves.
*/
private _linesCache: string[] = null;
private _linesCacheTimeoutId = 0;
constructor(private _terminal: ISearchAddonTerminal) {
// TODO: Search for multiple instances on 1 line
// TODO: Don't use the actual selection, instead use a "find selection" so multiple instances can be highlighted
// TODO: Highlight other instances in the viewport
this._destroyLinesCache = this._destroyLinesCache.bind(this);
}

@@ -29,28 +37,43 @@

public findNext(term: string, searchOptions?: ISearchOptions): boolean {
const selectionManager = this._terminal._core.selectionManager;
const {incremental} = searchOptions;
let result: ISearchResult;
if (!term || term.length === 0) {
selectionManager.clearSelection();
return false;
}
let result: ISearchResult;
let startCol: number = 0;
let startRow = this._terminal._core.buffer.ydisp;
let startRow = this._terminal._core.buffer.ydisp;
if (this._terminal._core.selectionManager.selectionEnd) {
if (selectionManager.selectionEnd) {
// Start from the selection end if there is a selection
// For incremental search, use existing row
if (this._terminal.getSelection().length !== 0) {
startRow = this._terminal._core.selectionManager.selectionEnd[1];
startRow = incremental ? selectionManager.selectionStart[1] : selectionManager.selectionEnd[1];
startCol = incremental ? selectionManager.selectionStart[0] : selectionManager.selectionEnd[0];
}
}
// Search from ydisp + 1 to end
for (let y = startRow + 1; y < this._terminal._core.buffer.ybase + this._terminal.rows; y++) {
result = this._findInLine(term, y, searchOptions);
if (result) {
break;
this._initLinesCache();
// Search startRow
result = this._findInLine(term, startRow, startCol, searchOptions);
// Search from startRow + 1 to end
if (!result) {
for (let y = startRow + 1; y < this._terminal._core.buffer.ybase + this._terminal.rows; y++) {
result = this._findInLine(term, y, 0, searchOptions);
if (result) {
break;
}
}
}
// Search from the top to the current ydisp
// Search from the top to the startRow (search the whole startRow again in
// case startCol > 0)
if (!result) {
for (let y = 0; y < startRow; y++) {
result = this._findInLine(term, y, searchOptions);
for (let y = 0; y <= startRow; y++) {
result = this._findInLine(term, y, 0, searchOptions);
if (result) {

@@ -74,28 +97,43 @@ break;

public findPrevious(term: string, searchOptions?: ISearchOptions): boolean {
const selectionManager = this._terminal._core.selectionManager;
let result: ISearchResult;
if (!term || term.length === 0) {
selectionManager.clearSelection();
return false;
}
let result: ISearchResult;
const isReverseSearch = true;
let startRow = this._terminal._core.buffer.ydisp;
let startCol: number = this._terminal._core.buffer.lines.get(startRow).length;
let startRow = this._terminal._core.buffer.ydisp;
if (this._terminal._core.selectionManager.selectionStart) {
// Start from the selection end if there is a selection
if (selectionManager.selectionStart) {
// Start from the selection start if there is a selection
if (this._terminal.getSelection().length !== 0) {
startRow = this._terminal._core.selectionManager.selectionStart[1];
startRow = selectionManager.selectionStart[1];
startCol = selectionManager.selectionStart[0];
}
}
// Search from ydisp + 1 to end
for (let y = startRow - 1; y >= 0; y--) {
result = this._findInLine(term, y, searchOptions);
if (result) {
break;
this._initLinesCache();
// Search startRow
result = this._findInLine(term, startRow, startCol, searchOptions, isReverseSearch);
// Search from startRow - 1 to top
if (!result) {
for (let y = startRow - 1; y >= 0; y--) {
result = this._findInLine(term, y, this._terminal._core.buffer.lines.get(y).length, searchOptions, isReverseSearch);
if (result) {
break;
}
}
}
// Search from the top to the current ydisp
// Search from the bottom to startRow (search the whole startRow again in
// case startCol > 0)
if (!result) {
for (let y = this._terminal._core.buffer.ybase + this._terminal.rows - 1; y > startRow; y--) {
result = this._findInLine(term, y, searchOptions);
const searchFrom = this._terminal._core.buffer.ybase + this._terminal.rows - 1;
for (let y = searchFrom; y >= startRow; y--) {
result = this._findInLine(term, y, this._terminal._core.buffer.lines.get(y).length, searchOptions, isReverseSearch);
if (result) {

@@ -112,2 +150,24 @@ break;

/**
* Sets up a line cache with a ttl
*/
private _initLinesCache(): void {
if (!this._linesCache) {
this._linesCache = new Array(this._terminal._core.buffer.length);
this._terminal.on('cursormove', this._destroyLinesCache);
}
window.clearTimeout(this._linesCacheTimeoutId);
this._linesCacheTimeoutId = window.setTimeout(() => this._destroyLinesCache(), LINES_CACHE_TIME_TO_LIVE);
}
private _destroyLinesCache(): void {
this._linesCache = null;
this._terminal.off('cursormove', this._destroyLinesCache);
if (this._linesCacheTimeoutId) {
window.clearTimeout(this._linesCacheTimeoutId);
this._linesCacheTimeoutId = 0;
}
}
/**
* A found substring is a whole word if it doesn't have an alphanumeric character directly adjacent to it.

@@ -119,4 +179,4 @@ * @param searchIndex starting indext of the potential whole word substring

private _isWholeWord(searchIndex: number, line: string, term: string): boolean {
return (((searchIndex === 0) || (nonWordCharacters.indexOf(line[searchIndex - 1]) !== -1)) &&
(((searchIndex + term.length) === line.length) || (nonWordCharacters.indexOf(line[searchIndex + term.length]) !== -1)));
return (((searchIndex === 0) || (NON_WORD_CHARACTERS.indexOf(line[searchIndex - 1]) !== -1)) &&
(((searchIndex + term.length) === line.length) || (NON_WORD_CHARACTERS.indexOf(line[searchIndex + term.length]) !== -1)));
}

@@ -130,40 +190,64 @@

* @param term The search term.
* @param y The line to search.
* @param row The line to start the search from.
* @param col The column to start the search from.
* @param searchOptions Search options.
* @return The search result if it was found.
*/
protected _findInLine(term: string, y: number, searchOptions: ISearchOptions = {}): ISearchResult {
if (this._terminal._core.buffer.lines.get(y).isWrapped) {
protected _findInLine(term: string, row: number, col: number, searchOptions: ISearchOptions = {}, isReverseSearch: boolean = false): ISearchResult {
if (this._terminal._core.buffer.lines.get(row).isWrapped) {
return;
}
const stringLine = this.translateBufferLineToStringWithWrap(y, true);
let stringLine = this._linesCache ? this._linesCache[row] : void 0;
if (stringLine === void 0) {
stringLine = this.translateBufferLineToStringWithWrap(row, true);
if (this._linesCache) {
this._linesCache[row] = stringLine;
}
}
const searchTerm = searchOptions.caseSensitive ? term : term.toLowerCase();
const searchStringLine = searchOptions.caseSensitive ? stringLine : stringLine.toLowerCase();
const searchTerm = searchOptions.caseSensitive ? term : term.toLowerCase();
let searchIndex = -1;
let resultIndex = -1;
if (searchOptions.regex) {
const searchRegex = RegExp(searchTerm, 'g');
const foundTerm = searchRegex.exec(searchStringLine);
if (foundTerm && foundTerm[0].length > 0) {
searchIndex = searchRegex.lastIndex - foundTerm[0].length;
term = foundTerm[0];
let foundTerm: RegExpExecArray;
if (isReverseSearch) {
// This loop will get the resultIndex of the _last_ regex match in the range 0..col
while (foundTerm = searchRegex.exec(searchStringLine.slice(0, col))) {
resultIndex = searchRegex.lastIndex - foundTerm[0].length;
term = foundTerm[0];
searchRegex.lastIndex -= (term.length - 1);
}
} else {
foundTerm = searchRegex.exec(searchStringLine.slice(col));
if (foundTerm && foundTerm[0].length > 0) {
resultIndex = col + (searchRegex.lastIndex - foundTerm[0].length);
term = foundTerm[0];
}
}
} else {
searchIndex = searchStringLine.indexOf(searchTerm);
if (isReverseSearch) {
if (col - searchTerm.length >= 0) {
resultIndex = searchStringLine.lastIndexOf(searchTerm, col - searchTerm.length);
}
} else {
resultIndex = searchStringLine.indexOf(searchTerm, col);
}
}
if (searchIndex >= 0) {
if (resultIndex >= 0) {
// Adjust the row number and search index if needed since a "line" of text can span multiple rows
if (searchIndex >= this._terminal.cols) {
y += Math.floor(searchIndex / this._terminal.cols);
searchIndex = searchIndex % this._terminal.cols;
if (resultIndex >= this._terminal.cols) {
row += Math.floor(resultIndex / this._terminal.cols);
resultIndex = resultIndex % this._terminal.cols;
}
if (searchOptions.wholeWord && !this._isWholeWord(searchIndex, searchStringLine, term)) {
if (searchOptions.wholeWord && !this._isWholeWord(resultIndex, searchStringLine, term)) {
return;
}
const line = this._terminal._core.buffer.lines.get(y);
const line = this._terminal._core.buffer.lines.get(row);
for (let i = 0; i < searchIndex; i++) {
for (let i = 0; i < resultIndex; i++) {
const charData = line.get(i);

@@ -173,3 +257,3 @@ // Adjust the searchIndex to normalize emoji into single chars

if (char.length > 1) {
searchIndex -= char.length - 1;
resultIndex -= char.length - 1;
}

@@ -180,3 +264,3 @@ // Adjust the searchIndex for empty characters following wide unicode

if (charWidth === 0) {
searchIndex++;
resultIndex++;
}

@@ -186,8 +270,7 @@ }

term,
col: searchIndex,
row: y
col: resultIndex,
row
};
}
}
/**

@@ -194,0 +277,0 @@ * Translates a buffer line to a string, including subsequent lines if they are wraps.

@@ -6,2 +6,3 @@ {

"lib": [
"dom",
"es5"

@@ -8,0 +9,0 @@ ],

@@ -17,3 +17,3 @@ /**

const hostClause = '((' + domainBodyClause + '\\.' + tldClause + ')|' + ipClause + '|' + localHostClause + ')' + portClause + '?';
const pathClause = '(\\/[\\/\\w\\.\\-%~:]*)*([^:\\s])';
const pathClause = '(\\/[\\/\\w\\.\\-%~:]*)*([^:"\'\\s])';
const queryStringHashFragmentCharacterSet = '[0-9\\w\\[\\]\\(\\)\\/\\?\\!#@$%&\'*+,:;~\\=\\.\\-]*';

@@ -20,0 +20,0 @@ const queryStringClause = '(\\?' + queryStringHashFragmentCharacterSet + ')?';

@@ -10,3 +10,4 @@ /**

const CHAR_DATA_CODE_INDEX = 3;
const NULL_CELL_CODE = 32;
const NULL_CELL_CODE = 0;
const WHITESPACE_CELL_CODE = 32;

@@ -36,3 +37,3 @@ export function winptyCompatInit(terminal: Terminal): void {

if (lastChar[CHAR_DATA_CODE_INDEX] !== NULL_CELL_CODE) {
if (lastChar[CHAR_DATA_CODE_INDEX] !== NULL_CELL_CODE && lastChar[CHAR_DATA_CODE_INDEX] !== WHITESPACE_CELL_CODE) {
const nextLine = addonTerminal._core.buffer.lines.get(addonTerminal._core.buffer.ybase + addonTerminal._core.buffer.y);

@@ -39,0 +40,0 @@ nextLine.isWrapped = true;

@@ -20,6 +20,10 @@ /**

export const NULL_CELL_CHAR = ' ';
export const NULL_CELL_CHAR = '';
export const NULL_CELL_WIDTH = 1;
export const NULL_CELL_CODE = 32;
export const NULL_CELL_CODE = 0;
export const WHITESPACE_CELL_CHAR = ' ';
export const WHITESPACE_CELL_WIDTH = 1;
export const WHITESPACE_CELL_CODE = 32;
/**

@@ -252,3 +256,3 @@ * This class represents a terminal buffer (an internal state of the terminal), where the

if (!line) {
[-1, -1];
return [-1, -1];
}

@@ -276,5 +280,3 @@ for (let i = 0; i < line.length; ++i) {

*/
public translateBufferLineToString(lineIndex: number, trimRight: boolean, startCol: number = 0, endCol: number = null): string {
// Get full line
let lineString = '';
public translateBufferLineToString(lineIndex: number, trimRight: boolean, startCol: number = 0, endCol?: number): string {
const line = this.lines.get(lineIndex);

@@ -284,54 +286,3 @@ if (!line) {

}
// Initialize column and index values. Column values represent the actual
// cell column, indexes represent the index in the string. Indexes are
// needed here because some chars are 0 characters long (eg. after wide
// chars) and some chars are longer than 1 characters long (eg. emojis).
let startIndex = startCol;
// Only set endCol to the line length when it is null. 0 is a valid column.
if (endCol === null) {
endCol = line.length;
}
let endIndex = endCol;
for (let i = 0; i < line.length; i++) {
const char = line.get(i);
lineString += char[CHAR_DATA_CHAR_INDEX];
// Adjust start and end cols for wide characters if they affect their
// column indexes
if (char[CHAR_DATA_WIDTH_INDEX] === 0) {
if (startCol >= i) {
startIndex--;
}
if (endCol > i) {
endIndex--;
}
} else {
// Adjust the columns to take glyphs that are represented by multiple
// code points into account.
if (char[CHAR_DATA_CHAR_INDEX].length > 1) {
if (startCol > i) {
startIndex += char[CHAR_DATA_CHAR_INDEX].length - 1;
}
if (endCol > i) {
endIndex += char[CHAR_DATA_CHAR_INDEX].length - 1;
}
}
}
}
// Calculate the final end col by trimming whitespace on the right of the
// line if needed.
if (trimRight) {
const rightWhitespaceIndex = lineString.search(/\s+$/);
if (rightWhitespaceIndex !== -1) {
endIndex = Math.min(endIndex, rightWhitespaceIndex);
}
// Return the empty string if only trimmed whitespace is selected
if (endIndex <= startIndex) {
return '';
}
}
return lineString.substring(startIndex, endIndex);
return line.translateToString(trimRight, startCol, endCol);
}

@@ -495,4 +446,3 @@

for (let i = range.first; i <= range.last; ++i) {
// TODO: always apply trimRight after fixing #1685
result += this._buffer.translateBufferLineToString(i, (this._trimRight) ? i === range.last : false);
result += this._buffer.translateBufferLineToString(i, this._trimRight);
}

@@ -499,0 +449,0 @@ this._current = range.last + 1;

@@ -6,3 +6,3 @@ /**

import { CharData, IBufferLine } from './Types';
import { NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR } from './Buffer';
import { NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR, CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, WHITESPACE_CELL_CHAR } from './Buffer';

@@ -111,2 +111,24 @@ /**

}
public getTrimmedLength(): number {
for (let i = this.length - 1; i >= 0; --i) {
const ch = this.get(i);
if (ch[CHAR_DATA_CHAR_INDEX] !== '') {
return i + ch[CHAR_DATA_WIDTH_INDEX];
}
}
return 0;
}
public translateToString(trimRight: boolean = false, startCol: number = 0, endCol: number = this.length): string {
if (trimRight) {
endCol = Math.min(endCol, this.getTrimmedLength());
}
let result = '';
while (startCol < endCol) {
result += this.get(startCol)[CHAR_DATA_CHAR_INDEX] || WHITESPACE_CELL_CHAR;
startCol += this.get(startCol)[CHAR_DATA_WIDTH_INDEX] || 1;
}
return result;
}
}

@@ -124,2 +146,5 @@

/** single vs. combined char distinction */
const IS_COMBINED_BIT_MASK = 0x80000000;
/**

@@ -150,7 +175,7 @@ * Typed array based bufferline implementation.

this._data[index * CELL_SIZE + Cell.FLAGS],
(stringData & 0x80000000)
(stringData & IS_COMBINED_BIT_MASK)
? this._combined[index]
: (stringData) ? String.fromCharCode(stringData) : '',
this._data[index * CELL_SIZE + Cell.WIDTH],
(stringData & 0x80000000)
(stringData & IS_COMBINED_BIT_MASK)
? this._combined[index].charCodeAt(this._combined[index].length - 1)

@@ -165,3 +190,3 @@ : stringData

this._combined[index] = value[1];
this._data[index * CELL_SIZE + Cell.STRING] = index | 0x80000000;
this._data[index * CELL_SIZE + Cell.STRING] = index | IS_COMBINED_BIT_MASK;
} else {

@@ -277,2 +302,24 @@ this._data[index * CELL_SIZE + Cell.STRING] = value[1].charCodeAt(0);

}
public getTrimmedLength(): number {
for (let i = this.length - 1; i >= 0; --i) {
if (this._data[i * CELL_SIZE + Cell.STRING] !== 0) { // 0 ==> ''.charCodeAt(0) ==> NaN ==> 0
return i + this._data[i * CELL_SIZE + Cell.WIDTH];
}
}
return 0;
}
public translateToString(trimRight: boolean = false, startCol: number = 0, endCol: number = this.length): string {
if (trimRight) {
endCol = Math.min(endCol, this.getTrimmedLength());
}
let result = '';
while (startCol < endCol) {
const stringData = this._data[startCol * CELL_SIZE + Cell.STRING];
result += (stringData & IS_COMBINED_BIT_MASK) ? this._combined[startCol] : (stringData) ? String.fromCharCode(stringData) : WHITESPACE_CELL_CHAR;
startCol += this._data[startCol * CELL_SIZE + Cell.WIDTH] || 1;
}
return result;
}
}

@@ -352,2 +352,6 @@ /**

}
} else if (ev.key && !ev.ctrlKey && !ev.altKey && !ev.metaKey &&
ev.keyCode >= 48 && ev.keyCode !== 144 && ev.keyCode !== 145) {
// Include only keys that that result in a character; don't include num lock and scroll lock
result.key = ev.key;
}

@@ -354,0 +358,0 @@ break;

@@ -70,3 +70,4 @@ /**

EXECUTABLES.push.apply(EXECUTABLES, r(0x1c, 0x20));
const DEFAULT_TRANSITION = ParserAction.ERROR << 4 | ParserState.GROUND;
// Pseudo-character placeholder for printable non-ascii characters.
const NON_ASCII_PRINTABLE = 0xA0;

@@ -83,6 +84,6 @@ /**

// table with default transition [any] --> DEFAULT_TRANSITION
// table with default transition
for (state in states) {
// NOTE: table lookup is capped at 0xa0 in parse to keep the table small
for (let code = 0; code < 160; ++code) {
for (let code = 0; code <= NON_ASCII_PRINTABLE; ++code) {
table.add(code, state, ParserAction.ERROR, ParserState.GROUND);

@@ -189,2 +190,3 @@ }

table.addMany([0x1b, 0x9c], ParserState.DCS_PASSTHROUGH, ParserAction.DCS_UNHOOK, ParserState.GROUND);
table.add(NON_ASCII_PRINTABLE, ParserState.OSC_STRING, ParserAction.OSC_PUT, ParserState.OSC_STRING);
return table;

@@ -397,3 +399,3 @@ })();

// normal transition & action lookup
transition = (code < 0xa0) ? (table[currentState << 8 | code]) : DEFAULT_TRANSITION;
transition = table[currentState << 8 | (code < 0xa0 ? code : NON_ASCII_PRINTABLE)];
switch (transition >> 4) {

@@ -430,6 +432,2 @@ case ParserAction.PRINT:

break;
case ParserState.OSC_STRING:
osc += String.fromCharCode(code);
transition |= ParserState.OSC_STRING;
break;
case ParserState.CSI_IGNORE:

@@ -525,3 +523,11 @@ transition |= ParserState.CSI_IGNORE;

case ParserAction.OSC_PUT:
osc += data.charAt(i);
for (let j = i + 1; ; j++) {
if (j >= l
|| (code = data.charCodeAt(j)) < 0x20
|| (code > 0x7f && code <= 0x9f)) {
osc += data.substring(i, j);
i = j - 1;
break;
}
}
break;

@@ -528,0 +534,0 @@ case ParserAction.OSC_END:

@@ -222,5 +222,13 @@ /**

rex.lastIndex = stringIndex + uri.length;
if (stringIndex < 0) {
// invalid stringIndex (should not have happened)
break;
}
// get the buffer index as [absolute row, col] for the match
const bufferIndex = this._terminal.buffer.stringIndexToBufferIndex(rowIndex, stringIndex);
if (bufferIndex[0] < 0) {
// invalid bufferIndex (should not have happened)
break;
}

@@ -227,0 +235,0 @@ const line = this._terminal.buffer.lines.get(bufferIndex[0]);

@@ -45,4 +45,2 @@ /**

// TODO: Currently if a terminal changes configs it will not free the entry reference (until it's disposed)
// Check to see if the terminal already owns this config

@@ -58,2 +56,3 @@ for (let i = 0; i < charAtlasCache.length; i++) {

if (entry.ownedBy.length === 1) {
entry.atlas.dispose();
charAtlasCache.splice(i, 1);

@@ -99,2 +98,3 @@ } else {

// Remove the cache entry if it's the only terminal
charAtlasCache[i].atlas.dispose();
charAtlasCache.splice(i, 1);

@@ -101,0 +101,0 @@ } else {

@@ -6,3 +6,3 @@ /**

import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_ATTR_INDEX, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CODE_INDEX, NULL_CELL_CODE } from '../../Buffer';
import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_ATTR_INDEX, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CODE_INDEX, NULL_CELL_CODE, WHITESPACE_CELL_CHAR } from '../../Buffer';
import { FLAGS } from '../Types';

@@ -45,3 +45,3 @@ import { IBufferLine } from '../../Types';

const charData = lineData.get(x);
const char = charData[CHAR_DATA_CHAR_INDEX];
const char = charData[CHAR_DATA_CHAR_INDEX] || WHITESPACE_CELL_CHAR;
const attr = charData[CHAR_DATA_ATTR_INDEX];

@@ -48,0 +48,0 @@ const width = charData[CHAR_DATA_WIDTH_INDEX];

@@ -6,3 +6,3 @@ /**

import { CHAR_DATA_ATTR_INDEX, CHAR_DATA_CODE_INDEX, CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, NULL_CELL_CODE } from '../Buffer';
import { CHAR_DATA_ATTR_INDEX, CHAR_DATA_CODE_INDEX, CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, NULL_CELL_CODE, WHITESPACE_CELL_CHAR, WHITESPACE_CELL_CODE } from '../Buffer';
import { FLAGS, IColorSet, IRenderDimensions, ICharacterJoinerRegistry } from './Types';

@@ -77,7 +77,7 @@ import { CharData, ITerminal } from '../Types';

const charData = line.get(x);
let code: number = <number>charData[CHAR_DATA_CODE_INDEX];
let code: number = <number>charData[CHAR_DATA_CODE_INDEX] || WHITESPACE_CELL_CODE;
// Can either represent character(s) for a single cell or multiple cells
// if indicated by a character joiner.
let chars: string = charData[CHAR_DATA_CHAR_INDEX];
let chars: string = charData[CHAR_DATA_CHAR_INDEX] || WHITESPACE_CELL_CHAR;
const attr: number = charData[CHAR_DATA_ATTR_INDEX];

@@ -84,0 +84,0 @@ let width: number = charData[CHAR_DATA_WIDTH_INDEX];

@@ -8,3 +8,3 @@ /**

import { XtermListener } from './common/Types';
import { MouseHelper } from './utils/MouseHelper';
import { MouseHelper } from './ui/MouseHelper';
import * as Browser from './core/Platform';

@@ -202,3 +202,3 @@ import { CharMeasure } from './ui/CharMeasure';

// Get first row
const startRowEndCol = start[1] === end[1] ? end[0] : null;
const startRowEndCol = start[1] === end[1] ? end[0] : undefined;
result.push(this._buffer.translateBufferLineToString(start[1], true, start[0], startRowEndCol));

@@ -205,0 +205,0 @@

@@ -16,3 +16,3 @@ /**

import { Terminal } from './Terminal';
import { CHAR_DATA_CHAR_INDEX } from './Buffer';
import { CHAR_DATA_CHAR_INDEX, WHITESPACE_CELL_CHAR } from './Buffer';
import { IViewport } from './Types';

@@ -71,3 +71,3 @@

for (let cell = 0; cell < term.cols; ++cell) {
lineText += term.buffer.lines.get(line).get(cell)[CHAR_DATA_CHAR_INDEX];
lineText += term.buffer.lines.get(line).get(cell)[CHAR_DATA_CHAR_INDEX] || WHITESPACE_CELL_CHAR;
}

@@ -74,0 +74,0 @@ // rtrim empty cells as xterm does

@@ -42,4 +42,3 @@ /**

import * as Strings from './Strings';
import { MouseHelper } from './utils/MouseHelper';
import { clone } from './utils/Clone';
import { MouseHelper } from './ui/MouseHelper';
import { DEFAULT_BELL_SOUND, SoundManager } from './SoundManager';

@@ -56,2 +55,3 @@ import { DEFAULT_ANSI_COLORS } from './renderer/ColorManager';

import { KeyboardResultType, ICharset } from './core/Types';
import { clone } from './common/Clone';

@@ -469,2 +469,3 @@ // Let it work inside Node.js for automated testing purposes.

}
break;
case 'rendererType':

@@ -471,0 +472,0 @@ if (this.renderer) {

@@ -248,3 +248,3 @@ /**

export interface IMouseHelper {
getCoords(event: { pageX: number, pageY: number }, element: HTMLElement, charMeasure: ICharMeasure, colCount: number, rowCount: number, isSelection?: boolean): [number, number];
getCoords(event: { clientX: number, clientY: number }, element: HTMLElement, charMeasure: ICharMeasure, colCount: number, rowCount: number, isSelection?: boolean): [number, number];
getRawByteCoords(event: MouseEvent, element: HTMLElement, charMeasure: ICharMeasure, colCount: number, rowCount: number): { x: number, y: number };

@@ -528,2 +528,4 @@ }

clone(): IBufferLine;
getTrimmedLength(): number;
translateToString(trimRight?: boolean, startCol?: number, endCol?: number): string;
}

@@ -530,0 +532,0 @@

@@ -41,3 +41,3 @@ /**

public measure(options: ITerminalOptions): void {
this._measureElement.style.fontFamily = options.fontFamily;
this._measureElement.style.fontFamily = options.fontFamily;
this._measureElement.style.fontSize = `${options.fontSize}px`;

@@ -44,0 +44,0 @@ const geometry = this._measureElement.getBoundingClientRect();

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc