diff --git a/terminus-ssh/src/api.ts b/terminus-ssh/src/api.ts index 36195d48..b9d394c3 100644 --- a/terminus-ssh/src/api.ts +++ b/terminus-ssh/src/api.ts @@ -363,6 +363,10 @@ export class SSHSession extends BaseSession { this.kill('TERM') } + supportsWorkingDirectory (): boolean { + return true + } + async getWorkingDirectory (): Promise { return null } diff --git a/terminus-terminal/src/api/baseTerminalTab.component.ts b/terminus-terminal/src/api/baseTerminalTab.component.ts index 07b444dc..c34a2ed9 100644 --- a/terminus-terminal/src/api/baseTerminalTab.component.ts +++ b/terminus-terminal/src/api/baseTerminalTab.component.ts @@ -18,6 +18,7 @@ import { TerminalDecorator } from './decorator' /** @hidden */ export interface ToastrServiceProxy { info: (_: string) => void + error: (_: string) => void } /** * A class to base your custom terminal tabs on @@ -140,7 +141,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit this.logger = this.log.create('baseTerminalTab') this.setTitle('Terminal') - this.hotkeysSubscription = this.hotkeys.matchedHotkey.subscribe(hotkey => { + this.hotkeysSubscription = this.hotkeys.matchedHotkey.subscribe(async hotkey => { if (!this.hasFocus) { return } @@ -207,6 +208,9 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit case 'pane-focus-all': this.focusAllPanes() break + case 'copy-current-path': + this.copyCurrentPath() + break } }) this.bellPlayer = document.createElement('audio') @@ -438,6 +442,19 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit } } + async copyCurrentPath (): Promise { + let cwd: string|null = null + if (this.session?.supportsWorkingDirectory()) { + cwd = await this.session.getWorkingDirectory() + } + if (cwd) { + this.electron.clipboard.writeText(cwd) + this.toastr.info('Copied') + } else { + this.toastr.error('Shell does not support current path detection') + } + } + /** @hidden */ ngOnDestroy (): void { this.frontend?.detach(this.content.nativeElement) diff --git a/terminus-terminal/src/config.ts b/terminus-terminal/src/config.ts index ae7a500b..2b24827c 100644 --- a/terminus-terminal/src/config.ts +++ b/terminus-terminal/src/config.ts @@ -4,6 +4,7 @@ import { ConfigProvider, Platform } from 'terminus-core' export class TerminalConfigProvider extends ConfigProvider { defaults = { hotkeys: { + 'copy-current-path': [], shell: { __nonStructural: true, }, diff --git a/terminus-terminal/src/hotkeys.ts b/terminus-terminal/src/hotkeys.ts index 205b8abb..d6fbb7e4 100644 --- a/terminus-terminal/src/hotkeys.ts +++ b/terminus-terminal/src/hotkeys.ts @@ -62,6 +62,10 @@ export class TerminalHotkeyProvider extends HotkeyProvider { id: 'ctrl-c', name: 'Intelligent Ctrl-C (copy/abort)', }, + { + id: 'copy-current-path', + name: 'Copy current path', + }, { id: 'search', name: 'Search', diff --git a/terminus-terminal/src/services/sessions.service.ts b/terminus-terminal/src/services/sessions.service.ts index cc598c60..72307842 100644 --- a/terminus-terminal/src/services/sessions.service.ts +++ b/terminus-terminal/src/services/sessions.service.ts @@ -87,6 +87,7 @@ export abstract class BaseSession { abstract kill (signal?: string): void abstract async getChildProcesses (): Promise abstract async gracefullyKillProcess (): Promise + abstract supportsWorkingDirectory (): boolean abstract async getWorkingDirectory (): Promise } @@ -259,6 +260,16 @@ export class Session extends BaseSession { } } + supportsWorkingDirectory (): boolean { + if (this.reportedCWD || this.guessedCWD) { + return true + } + if (!this.truePID) { + return false + } + return process.platform !== 'win32' + } + async getWorkingDirectory (): Promise { if (this.reportedCWD) { return this.reportedCWD diff --git a/terminus-terminal/src/tabContextMenu.ts b/terminus-terminal/src/tabContextMenu.ts index feeb433a..cc551aec 100644 --- a/terminus-terminal/src/tabContextMenu.ts +++ b/terminus-terminal/src/tabContextMenu.ts @@ -123,6 +123,13 @@ export class NewTabContextMenu extends TabContextMenuItemProvider { }) } + if (tab instanceof TerminalTabComponent && tab.session?.supportsWorkingDirectory()) { + items.push({ + label: 'Copy current path', + click: () => this.zone.run(() => tab.copyCurrentPath()), + }) + } + return items } }