added OSC52 support (remote copy)

This commit is contained in:
Eugene Pankov 2021-09-19 17:02:42 +02:00
parent d319a54fee
commit 02b7b12ea5
No known key found for this signature in database
GPG key ID: 5896FCBBDD1CF4F4
3 changed files with 40 additions and 21 deletions

View file

@ -701,6 +701,11 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
this.attachSessionHandler(this.session.destroyed$, () => {
this.setSession(null)
})
this.attachSessionHandler(this.session.oscProcessor.copyRequested$, content => {
this.platform.setClipboard({ text: content })
this.notifications.notice('Copied')
})
}
protected detachSessionHandlers (): void {

View file

@ -1,32 +1,46 @@
import * as os from 'os'
import { Subject, Observable } from 'rxjs'
const OSC1337Prefix = Buffer.from('\x1b]1337;')
const OSC1337Suffix = Buffer.from('\x07')
const OSCPrefix = Buffer.from('\x1b]')
const OSCSuffix = Buffer.from('\x07')
export class OSC1337Processor {
export class OSCProcessor {
get cwdReported$ (): Observable<string> { return this.cwdReported }
get copyRequested$ (): Observable<string> { return this.copyRequested }
private cwdReported = new Subject<string>()
private copyRequested = new Subject<string>()
process (data: Buffer): Buffer {
if (data.includes(OSC1337Prefix)) {
const preData = data.subarray(0, data.indexOf(OSC1337Prefix))
const params = data.subarray(data.indexOf(OSC1337Prefix) + OSC1337Prefix.length)
const postData = params.subarray(params.indexOf(OSC1337Suffix) + OSC1337Suffix.length)
const paramString = params.subarray(0, params.indexOf(OSC1337Suffix)).toString()
let startIndex = 0
while (data.includes(OSCPrefix, startIndex) && data.includes(OSCSuffix, startIndex)) {
const params = data.subarray(data.indexOf(OSCPrefix, startIndex) + OSCPrefix.length)
const oscString = params.subarray(0, params.indexOf(OSCSuffix)).toString()
if (paramString.startsWith('CurrentDir=')) {
let reportedCWD = paramString.split('=')[1]
if (reportedCWD.startsWith('~')) {
reportedCWD = os.homedir() + reportedCWD.substring(1)
startIndex = data.indexOf(OSCSuffix, startIndex) + OSCSuffix.length
const [oscCodeString, ...oscParams] = oscString.split(';')
const oscCode = parseInt(oscCodeString)
if (oscCode === 1337) {
const paramString = oscParams.join(';')
if (paramString.startsWith('CurrentDir=')) {
let reportedCWD = paramString.split('=')[1]
if (reportedCWD.startsWith('~')) {
reportedCWD = os.homedir() + reportedCWD.substring(1)
}
this.cwdReported.next(reportedCWD)
} else {
console.debug('Unsupported OSC 1337 parameter:', paramString)
}
} else if (oscCode === 52) {
if (oscParams[0] === 'c') {
const content = Buffer.from(oscParams[1], 'base64')
this.copyRequested.next(content.toString())
}
this.cwdReported.next(reportedCWD)
} else {
console.debug('Unsupported OSC 1337 parameter:', paramString)
continue
}
data = Buffer.concat([preData, postData])
}
return data
}

View file

@ -1,7 +1,7 @@
import { Observable, Subject } from 'rxjs'
import { Logger } from 'tabby-core'
import { LoginScriptProcessor, LoginScriptsOptions } from './api/loginScriptProcessing'
import { OSC1337Processor } from './api/osc1337Processing'
import { OSCProcessor } from './api/osc1337Processing'
/**
* A session object for a [[BaseTerminalTabComponent]]
@ -10,13 +10,13 @@ import { OSC1337Processor } from './api/osc1337Processing'
export abstract class BaseSession {
open: boolean
truePID?: number
oscProcessor = new OSCProcessor()
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
protected osc1337Processor = new OSC1337Processor()
private initialDataBuffer = Buffer.from('')
private initialDataBufferReleased = false
@ -26,13 +26,13 @@ export abstract class BaseSession {
get destroyed$ (): Observable<void> { return this.destroyed }
constructor (protected logger: Logger) {
this.osc1337Processor.cwdReported$.subscribe(cwd => {
this.oscProcessor.cwdReported$.subscribe(cwd => {
this.reportedCWD = cwd
})
}
emitOutput (data: Buffer): void {
data = this.osc1337Processor.process(data)
data = this.oscProcessor.process(data)
if (!this.initialDataBufferReleased) {
this.initialDataBuffer = Buffer.concat([this.initialDataBuffer, data])
} else {
@ -64,7 +64,7 @@ export abstract class BaseSession {
this.destroyed.next()
await this.gracefullyKillProcess()
}
this.osc1337Processor.close()
this.oscProcessor.close()
this.closed.complete()
this.destroyed.complete()
this.output.complete()