Eugene Pankov 6 лет назад
Родитель
Сommit
498564be9a

+ 1 - 0
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(),
         }
     }
 

+ 4 - 1
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

+ 3 - 0
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"
   },

+ 10 - 0
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)

+ 1 - 0
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(),
         }
     }
 

+ 3 - 0
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
 }

+ 6 - 0
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)

+ 15 - 0
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)

+ 4 - 1
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

+ 15 - 0
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"