From 498564be9a04ec0c06288556a1fc1d372552c35f Mon Sep 17 00:00:00 2001 From: Eugene Pankov Date: Wed, 5 Feb 2020 13:37:04 +0300 Subject: [PATCH] added scrollback saving --- terminus-ssh/src/components/sshTab.component.ts | 1 + terminus-ssh/src/recoveryProvider.ts | 5 ++++- terminus-terminal/package.json | 3 +++ .../src/api/baseTerminalTab.component.ts | 10 ++++++++++ .../src/components/terminalTab.component.ts | 1 + terminus-terminal/src/frontends/frontend.ts | 3 +++ terminus-terminal/src/frontends/htermFrontend.ts | 6 ++++++ terminus-terminal/src/frontends/xtermFrontend.ts | 15 +++++++++++++++ terminus-terminal/src/recoveryProvider.ts | 5 ++++- terminus-terminal/yarn.lock | 15 +++++++++++++++ 10 files changed, 62 insertions(+), 2 deletions(-) diff --git a/terminus-ssh/src/components/sshTab.component.ts b/terminus-ssh/src/components/sshTab.component.ts index 3e1da9f5..e069d3e0 100644 --- a/terminus-ssh/src/components/sshTab.component.ts +++ b/terminus-ssh/src/components/sshTab.component.ts @@ -69,6 +69,7 @@ export class SSHTabComponent extends BaseTerminalTabComponent { return { type: 'app:ssh-tab', connection: this.connection, + savedState: this.frontend.saveState(), } } diff --git a/terminus-ssh/src/recoveryProvider.ts b/terminus-ssh/src/recoveryProvider.ts index b59ac9d2..1f65b9f6 100644 --- a/terminus-ssh/src/recoveryProvider.ts +++ b/terminus-ssh/src/recoveryProvider.ts @@ -10,7 +10,10 @@ export class RecoveryProvider extends TabRecoveryProvider { if (recoveryToken && recoveryToken.type === 'app:ssh-tab') { return { type: SSHTabComponent, - options: { connection: recoveryToken.connection }, + options: { + connection: recoveryToken.connection, + savedState: recoveryToken.savedState, + }, } } return null diff --git a/terminus-terminal/package.json b/terminus-terminal/package.json index 8aab6657..b5c321f3 100644 --- a/terminus-terminal/package.json +++ b/terminus-terminal/package.json @@ -19,6 +19,7 @@ "devDependencies": { "@types/deep-equal": "^1.0.0", "@types/slug": "^0.9.1", + "ansi-colors": "^4.1.1", "dataurl": "0.1.0", "deep-equal": "1.1.0", "hterm-umdjs": "1.4.1", @@ -31,6 +32,8 @@ "xterm-addon-fit": "^0.4.0-beta2", "xterm-addon-ligatures": "^0.2.1", "xterm-addon-search": "^0.4.0", + "xterm-addon-serialize": "^0.1.1", + "xterm-addon-unicode11": "^0.1.1", "xterm-addon-webgl": "^0.5.0-beta.7", "zmodem.js": "^0.1.9" }, diff --git a/terminus-terminal/src/api/baseTerminalTab.component.ts b/terminus-terminal/src/api/baseTerminalTab.component.ts index 86a96327..9046d134 100644 --- a/terminus-terminal/src/api/baseTerminalTab.component.ts +++ b/terminus-terminal/src/api/baseTerminalTab.component.ts @@ -1,6 +1,7 @@ import { Observable, Subject, Subscription } from 'rxjs' import { first } from 'rxjs/operators' import { ToastrService } from 'ngx-toastr' +import colors from 'ansi-colors' import { NgZone, OnInit, OnDestroy, Inject, Injector, Optional, ViewChild, HostBinding, Input, ElementRef } from '@angular/core' import { trigger, transition, style, animate, AnimationTriggerMetadata } from '@angular/animations' import { AppService, ConfigService, BaseTabComponent, ElectronService, HostAppService, HotkeysService, Platform, LogService, Logger, TabContextMenuItemProvider } from 'terminus-core' @@ -34,6 +35,8 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit ])] session: BaseSession + savedState: any + @Input() zoom = 0 @Input() showSearchPanel = false @@ -178,6 +181,13 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit this.session.releaseInitialDataBuffer() }) + if (this.savedState) { + this.frontend.restoreState(this.savedState) + this.frontend.write('\r\n\r\n') + this.frontend.write(colors.bgWhite.black(' * ') + colors.bgBlackBright.white(' History restored ')) + this.frontend.write('\r\n\r\n') + } + setImmediate(() => { if (this.hasFocus) { this.frontend.attach(this.content.nativeElement) diff --git a/terminus-terminal/src/components/terminalTab.component.ts b/terminus-terminal/src/components/terminalTab.component.ts index 8c4e46b3..d33b9b9b 100644 --- a/terminus-terminal/src/components/terminalTab.component.ts +++ b/terminus-terminal/src/components/terminalTab.component.ts @@ -65,6 +65,7 @@ export class TerminalTabComponent extends BaseTerminalTabComponent { ...this.sessionOptions, cwd: cwd || this.sessionOptions.cwd, }, + savedState: this.frontend.saveState(), } } diff --git a/terminus-terminal/src/frontends/frontend.ts b/terminus-terminal/src/frontends/frontend.ts index f903750b..0b093751 100644 --- a/terminus-terminal/src/frontends/frontend.ts +++ b/terminus-terminal/src/frontends/frontend.ts @@ -74,4 +74,7 @@ export abstract class Frontend { abstract findNext (term: string, searchOptions?: SearchOptions): boolean abstract findPrevious (term: string, searchOptions?: SearchOptions): boolean + + abstract saveState (): any + abstract restoreState (state: any): void } diff --git a/terminus-terminal/src/frontends/htermFrontend.ts b/terminus-terminal/src/frontends/htermFrontend.ts index eceadfb2..9443b2e9 100644 --- a/terminus-terminal/src/frontends/htermFrontend.ts +++ b/terminus-terminal/src/frontends/htermFrontend.ts @@ -164,6 +164,12 @@ export class HTermFrontend extends Frontend { return false } + // eslint-disable-next-line @typescript-eslint/no-empty-function + saveState (): any { } + + // eslint-disable-next-line @typescript-eslint/no-empty-function + restoreState (_state: any): void { } + private setFontSize () { const size = this.configuredFontSize * Math.pow(1.1, this.zoom) preferenceManager.set('font-size', size) diff --git a/terminus-terminal/src/frontends/xtermFrontend.ts b/terminus-terminal/src/frontends/xtermFrontend.ts index 09f2a095..22a3813a 100644 --- a/terminus-terminal/src/frontends/xtermFrontend.ts +++ b/terminus-terminal/src/frontends/xtermFrontend.ts @@ -5,6 +5,8 @@ import { FitAddon } from 'xterm-addon-fit' import { LigaturesAddon } from 'xterm-addon-ligatures' import { SearchAddon } from 'xterm-addon-search' import { WebglAddon } from 'xterm-addon-webgl' +import { Unicode11Addon } from 'xterm-addon-unicode11' +import { SerializeAddon } from 'xterm-addon-serialize' import './xterm.css' import deepEqual from 'deep-equal' import { Attributes } from 'xterm/src/common/buffer/Constants' @@ -30,6 +32,7 @@ export class XTermFrontend extends Frontend { private copyOnSelect = false private search = new SearchAddon() private fitAddon = new FitAddon() + private serializeAddon = new SerializeAddon() private ligaturesAddon: LigaturesAddon private opened = false @@ -57,7 +60,11 @@ export class XTermFrontend extends Frontend { this.copySelection() } }) + this.xterm.loadAddon(this.fitAddon) + this.xterm.loadAddon(this.serializeAddon) + this.xterm.loadAddon(new Unicode11Addon()) + this.xterm.unicode.activeVersion = '11' const keyboardEventHandler = (name: string, event: KeyboardEvent) => { this.hotkeysService.pushKeystroke(name, event) @@ -248,6 +255,14 @@ export class XTermFrontend extends Frontend { return this.search.findPrevious(term, searchOptions) } + saveState (): any { + return this.serializeAddon.serialize() + } + + restoreState (state: any): void { + this.xterm.write(state) + } + private setFontSize () { const scale = Math.pow(1.1, this.zoom) this.xterm.setOption('fontSize', this.configuredFontSize * scale) diff --git a/terminus-terminal/src/recoveryProvider.ts b/terminus-terminal/src/recoveryProvider.ts index ebe4170c..248d01b3 100644 --- a/terminus-terminal/src/recoveryProvider.ts +++ b/terminus-terminal/src/recoveryProvider.ts @@ -10,7 +10,10 @@ export class RecoveryProvider extends TabRecoveryProvider { if (recoveryToken && recoveryToken.type === 'app:terminal-tab') { return { type: TerminalTabComponent, - options: { sessionOptions: recoveryToken.sessionOptions }, + options: { + sessionOptions: recoveryToken.sessionOptions, + savedState: recoveryToken.savedState, + }, } } return null diff --git a/terminus-terminal/yarn.lock b/terminus-terminal/yarn.lock index 1affe36d..7497959f 100644 --- a/terminus-terminal/yarn.lock +++ b/terminus-terminal/yarn.lock @@ -12,6 +12,11 @@ resolved "https://registry.yarnpkg.com/@types/slug/-/slug-0.9.1.tgz#16dbf8b77d73e0a09ce51a96400878f33806ab32" integrity sha512-zR/u8WFQ4/6uCIikjI00a5uB084XjgEGNRAvM4a1BL39Bw9yEiDQFiPS2DgJ8lPDkR2Qd/vZ26dCR9XqlKbDqQ== +ansi-colors@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + any-promise@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" @@ -249,6 +254,16 @@ xterm-addon-search@^0.4.0: resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.4.0.tgz#a7beadb3caa7330eb31fb1f17d92de25537684a1" integrity sha512-g07qb/Z4aSfrQ25e6Z6rz6KiExm2DvesQXkx+eA715VABBr5VM/9Jf0INoCiDSYy/nn7rpna+kXiGVJejIffKg== +xterm-addon-serialize@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.1.1.tgz#0fdff59702c00ed8288181198153ec47fd3df8da" + integrity sha512-6ykkAnyVsMZhKhUAR6Uml1t8kwpmPqoZm8qERfQX+kI4+m6UGf9ec4SLteDGpYMh/6hLrN7WZqSukfsU3Eof9g== + +xterm-addon-unicode11@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.1.1.tgz#b209ef137db38096f68636af4ef4d0c0acba85ad" + integrity sha512-z6vJTL+dpNljwAYzYoyDjJP8A2XjZuEosl0sRa+FGRf3jEyEVWquDM53MfUd1ztVdAPQ839qR6eYK1BXV04Bhw== + xterm-addon-webgl@^0.5.0-beta.7: version "0.5.0" resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.5.0.tgz#c1031dc7599cce3509824643ab5f15361c928e3e"