diff --git a/tabby-terminal/src/api/baseTerminalTab.component.ts b/tabby-terminal/src/api/baseTerminalTab.component.ts index 06775ef3..ef3e478e 100644 --- a/tabby-terminal/src/api/baseTerminalTab.component.ts +++ b/tabby-terminal/src/api/baseTerminalTab.component.ts @@ -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 { diff --git a/tabby-terminal/src/api/osc1337Processing.ts b/tabby-terminal/src/api/osc1337Processing.ts index 58e61169..1a0aacbc 100644 --- a/tabby-terminal/src/api/osc1337Processing.ts +++ b/tabby-terminal/src/api/osc1337Processing.ts @@ -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 { return this.cwdReported } + get copyRequested$ (): Observable { return this.copyRequested } private cwdReported = new Subject() + private copyRequested = new Subject() 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 } diff --git a/tabby-terminal/src/session.ts b/tabby-terminal/src/session.ts index 425c7b8b..f390ae10 100644 --- a/tabby-terminal/src/session.ts +++ b/tabby-terminal/src/session.ts @@ -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() protected binaryOutput = new Subject() protected closed = new Subject() protected destroyed = new Subject() 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 { 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()