-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
/
Copy pathsession.ts
94 lines (83 loc) · 3.42 KB
/
session.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import { Observable, Subject } from 'rxjs'
import { Logger } from 'tabby-core'
import { LoginScriptProcessor, LoginScriptsOptions } from './middleware/loginScriptProcessing'
import { OSCProcessor } from './middleware/oscProcessing'
import { SessionMiddlewareStack } from './api/middleware'
/**
* A session object for a [[BaseTerminalTabComponent]]
* Extend this to implement custom I/O and process management for your terminal tab
*/
export abstract class BaseSession {
open: boolean
readonly oscProcessor = new OSCProcessor()
readonly middleware = new SessionMiddlewareStack()
protected output = new Subject<string>()
protected binaryOutput = new Subject<Buffer>()
protected closed = new Subject<void>()
protected destroyed = new Subject<void>()
protected loginScriptProcessor: LoginScriptProcessor | null = null
protected reportedCWD?: string
private initialDataBuffer = Buffer.from('')
private initialDataBufferReleased = false
get output$ (): Observable<string> { return this.output }
get binaryOutput$ (): Observable<Buffer> { return this.binaryOutput }
get closed$ (): Observable<void> { return this.closed }
get destroyed$ (): Observable<void> { return this.destroyed }
constructor (protected logger: Logger) {
this.middleware.push(this.oscProcessor)
this.oscProcessor.cwdReported$.subscribe(cwd => {
this.reportedCWD = cwd
})
this.middleware.outputToTerminal$.subscribe(data => {
if (!this.initialDataBufferReleased) {
this.initialDataBuffer = Buffer.concat([this.initialDataBuffer, data])
} else {
this.output.next(data.toString())
this.binaryOutput.next(data)
}
})
this.middleware.outputToSession$.subscribe(data => this.write(data))
}
feedFromTerminal (data: Buffer): void {
this.middleware.feedFromTerminal(data)
}
protected emitOutput (data: Buffer): void {
this.middleware.feedFromSession(data)
}
releaseInitialDataBuffer (): void {
this.initialDataBufferReleased = true
this.output.next(this.initialDataBuffer.toString())
this.binaryOutput.next(this.initialDataBuffer)
this.initialDataBuffer = Buffer.from('')
}
setLoginScriptsOptions (options: LoginScriptsOptions): void {
const newProcessor = new LoginScriptProcessor(this.logger, options)
if (this.loginScriptProcessor) {
this.middleware.replace(this.loginScriptProcessor, newProcessor)
} else {
this.middleware.push(newProcessor)
}
this.loginScriptProcessor = newProcessor
}
async destroy (): Promise<void> {
if (this.open) {
this.logger.info('Destroying')
this.open = false
this.closed.next()
this.destroyed.next()
await this.gracefullyKillProcess()
}
this.middleware.close()
this.closed.complete()
this.destroyed.complete()
this.output.complete()
this.binaryOutput.complete()
}
abstract start (options: unknown): Promise<void>
abstract resize (columns: number, rows: number): void
abstract write (data: Buffer): void
abstract kill (signal?: string): void
abstract gracefullyKillProcess (): Promise<void>
abstract supportsWorkingDirectory (): boolean
abstract getWorkingDirectory (): Promise<string|null>
}