From 589b7ea46c6de7b87b4971b391b0b0547545161e Mon Sep 17 00:00:00 2001 From: Eugene Pankov Date: Thu, 13 Jun 2019 14:26:02 +0200 Subject: [PATCH] bumped xterm --- terminus-terminal/package.json | 6 +- .../src/frontends/xtermAddonFit.ts | 79 ----- .../src/frontends/xtermFrontend.ts | 9 +- .../src/frontends/xtermSearchAddon.ts | 328 ------------------ terminus-terminal/yarn.lock | 16 +- 5 files changed, 22 insertions(+), 416 deletions(-) delete mode 100644 terminus-terminal/src/frontends/xtermAddonFit.ts delete mode 100644 terminus-terminal/src/frontends/xtermSearchAddon.ts diff --git a/terminus-terminal/package.json b/terminus-terminal/package.json index cf9f048e..0f73378c 100644 --- a/terminus-terminal/package.json +++ b/terminus-terminal/package.json @@ -31,8 +31,10 @@ "runes": "^0.4.2", "slug": "^1.1.0", "uuid": "^3.3.2", - "xterm": "https://registry.npmjs.org/@terminus-term/xterm/-/xterm-3.14.1.tgz", - "xterm-addon-ligatures": "^0.1.0-beta-2" + "xterm": "https://registry.npmjs.org/@terminus-term/xterm/-/xterm-3.14.2.tgz", + "xterm-addon-fit": "^0.1.0-beta3", + "xterm-addon-ligatures": "^0.1.0-beta-2", + "xterm-addon-search": "^0.1.0-beta6" }, "peerDependencies": { "@angular/common": "4.0.1", diff --git a/terminus-terminal/src/frontends/xtermAddonFit.ts b/terminus-terminal/src/frontends/xtermAddonFit.ts deleted file mode 100644 index f2c37141..00000000 --- a/terminus-terminal/src/frontends/xtermAddonFit.ts +++ /dev/null @@ -1,79 +0,0 @@ -/** - * Copyright (c) 2017 The xterm.js authors. All rights reserved. - * @license MIT - */ - -import { Terminal, ITerminalAddon } from 'xterm'; - -interface ITerminalDimensions { - /** - * The number of rows in the terminal. - */ - rows: number; - - /** - * The number of columns in the terminal. - */ - cols: number; -} - -export class FitAddon implements ITerminalAddon { - private _terminal: Terminal | undefined; - - constructor() {} - - public activate(terminal: Terminal): void { - this._terminal = terminal; - } - - public dispose(): void {} - - public fit(): void { - const dims = this.proposeDimensions(); - if (!dims || !this._terminal) { - return; - } - - // TODO: Remove reliance on private API - const core = (this._terminal)._core; - - // Force a full render - if (this._terminal.rows !== dims.rows || this._terminal.cols !== dims.cols) { - core._renderCoordinator.clear(); - this._terminal.resize(dims.cols, dims.rows); - } - } - - public proposeDimensions(): ITerminalDimensions | undefined { - if (!this._terminal) { - return undefined; - } - - if (!this._terminal.element.parentElement) { - return undefined; - } - - // TODO: Remove reliance on private API - const core = (this._terminal)._core; - - const parentElementStyle = window.getComputedStyle(this._terminal.element.parentElement); - const parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height')); - const parentElementWidth = Math.max(0, parseInt(parentElementStyle.getPropertyValue('width'))); - const elementStyle = window.getComputedStyle(this._terminal.element); - const elementPadding = { - top: parseInt(elementStyle.getPropertyValue('padding-top')), - bottom: parseInt(elementStyle.getPropertyValue('padding-bottom')), - right: parseInt(elementStyle.getPropertyValue('padding-right')), - left: parseInt(elementStyle.getPropertyValue('padding-left')) - }; - const elementPaddingVer = elementPadding.top + elementPadding.bottom; - const elementPaddingHor = elementPadding.right + elementPadding.left; - const availableHeight = parentElementHeight - elementPaddingVer; - const availableWidth = parentElementWidth - elementPaddingHor - core.viewport.scrollBarWidth; - const geometry = { - cols: Math.floor(availableWidth / core._renderCoordinator.dimensions.actualCellWidth), - rows: Math.floor(availableHeight / core._renderCoordinator.dimensions.actualCellHeight) - }; - return geometry; - } -} diff --git a/terminus-terminal/src/frontends/xtermFrontend.ts b/terminus-terminal/src/frontends/xtermFrontend.ts index af43f84f..33575494 100644 --- a/terminus-terminal/src/frontends/xtermFrontend.ts +++ b/terminus-terminal/src/frontends/xtermFrontend.ts @@ -1,12 +1,12 @@ import { Frontend } from './frontend' import { Terminal, ITheme } from 'xterm' import { getCSSFontFamily } from '../utils' -import { FitAddon } from './xtermAddonFit' +import { FitAddon } from 'xterm-addon-fit' import { enableLigatures } from 'xterm-addon-ligatures' -import { SearchAddon, ISearchOptions } from './xtermSearchAddon' +import { SearchAddon, ISearchOptions } from 'xterm-addon-search' import './xterm.css' import deepEqual = require('deep-equal') -import { Attributes, AttributeData, CellData } from 'xterm/src/core/buffer/BufferLine' +import { Attributes, AttributeData, CellData } from 'xterm/src/common/buffer/BufferLine' const COLOR_NAMES = [ 'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', @@ -83,8 +83,9 @@ export class XTermFrontend extends Frontend { this.resizeHandler = () => { try { this.fitAddon.fit() - } catch { + } catch (e) { // tends to throw when element wasn't shown yet + console.warn('Could not resize xterm', e) } } diff --git a/terminus-terminal/src/frontends/xtermSearchAddon.ts b/terminus-terminal/src/frontends/xtermSearchAddon.ts deleted file mode 100644 index e2839a3e..00000000 --- a/terminus-terminal/src/frontends/xtermSearchAddon.ts +++ /dev/null @@ -1,328 +0,0 @@ -/** -* Copyright (c) 2017 The xterm.js authors. All rights reserved. -* @license MIT -*/ - -import { Terminal, IDisposable, ITerminalAddon } from 'xterm' - -export interface ISearchOptions { - regex?: boolean - wholeWord?: boolean - caseSensitive?: boolean - incremental?: boolean -} - -export interface ISearchResult { - term: string - col: number - row: number -} - -const NON_WORD_CHARACTERS = ' ~!@#$%^&*()+`-=[]{}|\;:"\',./<>?' -const LINES_CACHE_TIME_TO_LIVE = 15 * 1000 // 15 secs - -export class SearchAddon implements ITerminalAddon { - private _terminal: Terminal | undefined - - private _linesCache: string[] | undefined - private _linesCacheTimeoutId = 0 - private _cursorMoveListener: IDisposable | undefined - private _resizeListener: IDisposable | undefined - - public activate (terminal: Terminal): void { - this._terminal = terminal - } - - public dispose (): void {} - - public findNext (term: string, searchOptions?: ISearchOptions): boolean { - if (!this._terminal) { - throw new Error('Cannot use addon until it has been loaded') - } - - if (!term || term.length === 0) { - this._terminal.clearSelection() - return false - } - - let startCol: number = 0 - let startRow = this._terminal.buffer.viewportY - - if (this._terminal.hasSelection()) { - const incremental = searchOptions ? searchOptions.incremental : false - // Start from the selection end if there is a selection - // For incremental search, use existing row - const currentSelection = this._terminal.getSelectionPosition()! - startRow = incremental ? currentSelection.startRow : currentSelection.endRow - startCol = incremental ? currentSelection.startColumn : currentSelection.endColumn - } - - this._initLinesCache() - - // A row that has isWrapped = false - let findingRow = startRow - // index of beginning column that _findInLine need to scan. - let cumulativeCols = startCol - // If startRow is wrapped row, scan for unwrapped row above. - // So we can start matching on wrapped line from long unwrapped line. - let currentLine = this._terminal.buffer.getLine(findingRow) - while (currentLine && currentLine.isWrapped) { - cumulativeCols += this._terminal.cols - currentLine = this._terminal.buffer.getLine(--findingRow) - } - - // Search startRow - let result = this._findInLine(term, findingRow, cumulativeCols, searchOptions) - - // Search from startRow + 1 to end - if (!result) { - - for (let y = startRow + 1; y < this._terminal.buffer.baseY + this._terminal.rows; y++) { - - // If the current line is wrapped line, increase index of column to ignore the previous scan - // Otherwise, reset beginning column index to zero with set new unwrapped line index - result = this._findInLine(term, y, 0, searchOptions) - if (result) { - break - } - } - } - - // Search from the top to the startRow (search the whole startRow again in - // case startCol > 0) - if (!result) { - for (let y = 0; y < findingRow; y++) { - result = this._findInLine(term, y, 0, searchOptions) - if (result) { - break - } - } - } - - // Set selection and scroll if a result was found - return this._selectResult(result) - } - - public findPrevious (term: string, searchOptions?: ISearchOptions): boolean { - if (!this._terminal) { - throw new Error('Cannot use addon until it has been loaded') - } - - if (!term || term.length === 0) { - this._terminal.clearSelection() - return false - } - - const isReverseSearch = true - let startRow = this._terminal.buffer.viewportY + this._terminal.rows - 1 - let startCol = this._terminal.cols - - if (this._terminal.hasSelection()) { - // Start from the selection start if there is a selection - const currentSelection = this._terminal.getSelectionPosition()! - startRow = currentSelection.startRow - startCol = currentSelection.startColumn - } - - this._initLinesCache() - - // Search startRow - let result = this._findInLine(term, startRow, startCol, searchOptions, isReverseSearch) - - // Search from startRow - 1 to top - if (!result) { - // If the line is wrapped line, increase number of columns that is needed to be scanned - // Se we can scan on wrapped line from unwrapped line - let cumulativeCols = this._terminal.cols - if (this._terminal.buffer.getLine(startRow)!.isWrapped) { - cumulativeCols += startCol - } - for (let y = startRow - 1; y >= 0; y--) { - result = this._findInLine(term, y, cumulativeCols, searchOptions, isReverseSearch) - if (result) { - break - } - // If the current line is wrapped line, increase scanning range, - // preparing for scanning on unwrapped line - const line = this._terminal.buffer.getLine(y) - if (line && line.isWrapped) { - cumulativeCols += this._terminal.cols - } else { - cumulativeCols = this._terminal.cols - } - } - } - - // Search from the bottom to startRow (search the whole startRow again in - // case startCol > 0) - if (!result) { - const searchFrom = this._terminal.buffer.baseY + this._terminal.rows - 1 - let cumulativeCols = this._terminal.cols - for (let y = searchFrom; y >= startRow; y--) { - result = this._findInLine(term, y, cumulativeCols, searchOptions, isReverseSearch) - if (result) { - break - } - const line = this._terminal.buffer.getLine(y) - if (line && line.isWrapped) { - cumulativeCols += this._terminal.cols - } else { - cumulativeCols = this._terminal.cols - } - } - } - - // Set selection and scroll if a result was found - return this._selectResult(result) - } - - private _initLinesCache (): void { - const terminal = this._terminal! - if (!this._linesCache) { - this._linesCache = new Array(terminal.buffer.length) - this._cursorMoveListener = terminal.onCursorMove(() => this._destroyLinesCache()) - this._resizeListener = terminal.onResize(() => this._destroyLinesCache()) - } - - window.clearTimeout(this._linesCacheTimeoutId) - this._linesCacheTimeoutId = window.setTimeout(() => this._destroyLinesCache(), LINES_CACHE_TIME_TO_LIVE) - } - - private _destroyLinesCache (): void { - this._linesCache = undefined - if (this._cursorMoveListener) { - this._cursorMoveListener.dispose() - this._cursorMoveListener = undefined - } - if (this._resizeListener) { - this._resizeListener.dispose() - this._resizeListener = undefined - } - if (this._linesCacheTimeoutId) { - window.clearTimeout(this._linesCacheTimeoutId) - this._linesCacheTimeoutId = 0 - } - } - - private _isWholeWord (searchIndex: number, line: string, term: string): boolean { - 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))) - } - - protected _findInLine (term: string, row: number, col: number, searchOptions: ISearchOptions = {}, isReverseSearch: boolean = false): ISearchResult | undefined { - const terminal = this._terminal! - - // Ignore wrapped lines, only consider on unwrapped line (first row of command string). - const firstLine = terminal.buffer.getLine(row) - if (firstLine && firstLine.isWrapped) { - return null - } - 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() - - let resultIndex = -1 - if (searchOptions.regex) { - const searchRegex = RegExp(searchTerm, 'g') - let foundTerm: RegExpExecArray | null - 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 { - if (isReverseSearch) { - if (col - searchTerm.length >= 0) { - resultIndex = searchStringLine.lastIndexOf(searchTerm, col - searchTerm.length) - } - } else { - resultIndex = searchStringLine.indexOf(searchTerm, col) - } - } - - if (resultIndex >= 0) { - // Adjust the row number and search index if needed since a "line" of text can span multiple rows - if (resultIndex >= terminal.cols) { - row += Math.floor(resultIndex / terminal.cols) - resultIndex = resultIndex % terminal.cols - } - if (searchOptions.wholeWord && !this._isWholeWord(resultIndex, searchStringLine, term)) { - return null - } - - const line = terminal.buffer.getLine(row) - - if (line) { - for (let i = 0; i < resultIndex; i++) { - const cell = line.getCell(i) - if (!cell) { - break - } - // Adjust the searchIndex to normalize emoji into single chars - const char = cell.char - if (char.length > 1) { - resultIndex -= char.length - 1 - } - // Adjust the searchIndex for empty characters following wide unicode - // chars (eg. CJK) - const charWidth = cell.width - if (charWidth === 0) { - resultIndex++ - } - } - } - return { - term, - col: resultIndex, - row - } - } - return null - } - - private _translateBufferLineToStringWithWrap (lineIndex: number, trimRight: boolean): string { - const terminal = this._terminal! - let lineString = '' - let lineWrapsToNext: boolean - - do { - const nextLine = terminal.buffer.getLine(lineIndex + 1) - lineWrapsToNext = nextLine ? nextLine.isWrapped : false - const line = terminal.buffer.getLine(lineIndex) - if (!line) { - break - } - lineString += line.translateToString(!lineWrapsToNext && trimRight).substring(0, terminal.cols) - lineIndex++ - } while (lineWrapsToNext) - - return lineString - } - - private _selectResult (result: ISearchResult | undefined): boolean { - const terminal = this._terminal! - if (!result) { - terminal.clearSelection() - return false - } - terminal.select(result.col, result.row, result.term.length) - terminal.scrollLines(result.row - terminal.buffer.viewportY) - return true - } -} diff --git a/terminus-terminal/yarn.lock b/terminus-terminal/yarn.lock index 97715d57..5190c1b3 100644 --- a/terminus-terminal/yarn.lock +++ b/terminus-terminal/yarn.lock @@ -246,6 +246,11 @@ windows-native-registry@^1.0.14: dependencies: nan "^2.13.2" +xterm-addon-fit@^0.1.0-beta3: + version "0.1.0-beta3" + resolved "https://registry.yarnpkg.com/xterm-addon-fit/-/xterm-addon-fit-0.1.0-beta3.tgz#82bc2474cb00a2872d9a43ea52ed801bdfeebeaf" + integrity sha512-5UWwCH3smDWlqskK8r0GcCgLPvwbJiPpKiM01E67g5HIrQqCxITKawc01cuKCDLVj03sFJB9jDCOoh0n0mN+Zw== + xterm-addon-ligatures@^0.1.0-beta-2: version "0.1.0-beta-2" resolved "https://registry.yarnpkg.com/xterm-addon-ligatures/-/xterm-addon-ligatures-0.1.0-beta-2.tgz#def635fd0ca671fe61179629f8492b76c66dec6e" @@ -254,9 +259,14 @@ xterm-addon-ligatures@^0.1.0-beta-2: font-finder "^1.0.2" font-ligatures "^1.3.1" -"xterm@https://registry.npmjs.org/@terminus-term/xterm/-/xterm-3.14.1.tgz": - version "3.14.1" - resolved "https://registry.npmjs.org/@terminus-term/xterm/-/xterm-3.14.1.tgz#f3f7c0b4726fc60c22af17bac95c1b8058eca317" +xterm-addon-search@^0.1.0-beta6: + version "0.1.0-beta6" + resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.1.0-beta6.tgz#e2a2b441f8f7b0245c63731d0b2af32c7d4e6747" + integrity sha512-XKxdfO48HkCJW2m1wXW0PK/BOk00WEaN+W2LgDQqCBwwUjyBzWc9HaV8gzLXhSCDAYesWvtQa3RfqHfSp9qsbQ== + +"xterm@https://registry.npmjs.org/@terminus-term/xterm/-/xterm-3.14.2.tgz": + version "3.14.2" + resolved "https://registry.npmjs.org/@terminus-term/xterm/-/xterm-3.14.2.tgz#3ad13ca05ef024e8fb993d5c8320ca56a43eaf8e" yallist@^2.1.2: version "2.1.2"