Merge commit from fork

* improve quoting of dropped paths

* Update pathDrop.ts
This commit is contained in:
Eugene
2026-05-17 11:58:55 +02:00
committed by GitHub
parent fdd3945d05
commit e151472b95
15 changed files with 77 additions and 8 deletions
+52 -8
View File
@@ -1,11 +1,12 @@
import { Injectable } from '@angular/core'
import { TerminalDecorator, BaseTerminalTabComponent } from 'tabby-terminal'
import { TerminalDecorator, BaseTerminalTabComponent, BaseTerminalProfile } from 'tabby-terminal'
import { webUtils } from 'electron'
import { ShellType, TerminalTabComponent } from 'tabby-local'
/** @hidden */
@Injectable()
export class PathDropDecorator extends TerminalDecorator {
attach (terminal: BaseTerminalTabComponent<any>): void {
attach (terminal: BaseTerminalTabComponent<BaseTerminalProfile>): void {
setTimeout(() => {
this.subscribeUntilDetached(terminal, terminal.frontend?.dragOver$.subscribe(event => {
event.preventDefault()
@@ -19,12 +20,55 @@ export class PathDropDecorator extends TerminalDecorator {
})
}
private injectPath (terminal: BaseTerminalTabComponent<any>, path: string) {
path = path.replace(/[\x00-\x1F\x7F]/g, '')
if (path.includes(' ')) {
path = `"${path}"`
private injectPath (terminal: BaseTerminalTabComponent<BaseTerminalProfile>, path: string) {
const shellType = this.getShellType(terminal)
let data = this.quotePath(path, shellType) + ' '
if (terminal.config.store.terminal.bracketedPaste && terminal.frontend?.supportsBracketedPaste()) {
data = `\x1b[200~${data}\x1b[201~`
}
path = path.replaceAll('\\', '\\\\')
terminal.sendInput(path + ' ')
terminal.sendInput(data)
}
private getShellType (terminal: BaseTerminalTabComponent<BaseTerminalProfile>): ShellType {
const profileShellType = terminal instanceof TerminalTabComponent ? terminal.profile.options.shellType : null
return profileShellType ?? 'unix'
}
private quotePath (path: string, shellType: ShellType): string {
path = path.replace(/[\x00-\x1F\x7F]/g, '')
if (shellType === 'powershell') {
return this.quoteForPowerShell(path)
}
if (shellType === 'cmd') {
return this.quoteForCmd(path)
}
return this.quoteForUnix(path)
}
private quoteForUnix (path: string): string {
return `'${path.replace(/'/g, `'\\''`)}'`
}
private quoteForPowerShell (path: string): string {
// double any single-quote-class chars already present
return `'${path.replace(/['\u2018\u2019\u201A\u201B]/g, m => m + m)}'`
}
private quoteForCmd (path: string): string {
if (!path) {
return '""'
}
const escaped = path
.replace(/\^/g, '^^')
.replace(/!/g, '^!')
.replace(/"/g, '""')
.replace(/%/g, '%%')
return `"${escaped}"`
}
}
+2
View File
@@ -35,6 +35,7 @@ export class CmderShellProvider extends ShellProvider {
env: {
TERM: 'cygwin',
},
shellType: 'cmd',
},
{
id: 'cmderps',
@@ -51,6 +52,7 @@ export class CmderShellProvider extends ShellProvider {
],
icon: require('../icons/cmder-powershell.svg'),
env: {},
shellType: 'powershell',
},
]
}
+1
View File
@@ -39,6 +39,7 @@ export class Cygwin32ShellProvider extends ShellProvider {
env: {
TERM: 'cygwin',
},
shellType: 'unix',
}]
}
}
+1
View File
@@ -39,6 +39,7 @@ export class Cygwin64ShellProvider extends ShellProvider {
env: {
TERM: 'cygwin',
},
shellType: 'unix',
}]
}
}
+1
View File
@@ -44,6 +44,7 @@ export class GitBashShellProvider extends WindowsBaseShellProvider {
args: ['--login', '-i'],
icon: require('../icons/git-bash.svg'),
env: this.getEnvironment(),
shellType: 'unix',
}]
}
}
@@ -31,6 +31,7 @@ export class LinuxDefaultShellProvider extends ShellProvider {
name: this.translate.instant('User default'),
command: '/bin/sh',
env: {},
shellType: 'unix',
}]
} else {
return [{
@@ -40,6 +41,7 @@ export class LinuxDefaultShellProvider extends ShellProvider {
args: ['--login'],
hidden: true,
env: {},
shellType: 'unix',
}]
}
}
+1
View File
@@ -27,6 +27,7 @@ export class MacOSDefaultShellProvider extends ShellProvider {
args: ['--login'],
hidden: true,
env: {},
shellType: 'unix',
}]
}
+1
View File
@@ -43,6 +43,7 @@ export class MSYS2ShellProvider extends ShellProvider {
icon: require('../icons/msys2.svg'),
env: {},
cwd: homePath,
shellType: 'unix',
}))
}
}
+1
View File
@@ -36,6 +36,7 @@ export class POSIXShellsProvider extends ShellProvider {
command: x,
args: ['-l'],
env: {},
shellType: 'unix',
}))
}
}
@@ -39,6 +39,7 @@ export class PowerShellCoreShellProvider extends WindowsBaseShellProvider {
args: ['-nologo'],
icon: require('../icons/powershell-core.svg'),
env: this.getEnvironment(),
shellType: 'powershell',
}]
}
}
+1
View File
@@ -48,6 +48,7 @@ export class VSDevToolsProvider extends ShellProvider {
args: ['/k', bat],
icon: vsIconMap[version],
env: {},
shellType: 'cmd',
})
}
} catch (_) {
@@ -52,6 +52,7 @@ export class WindowsStockShellsProvider extends WindowsBaseShellProvider {
WT_SESSION: '0',
},
icon: require('../icons/clink.svg'),
shellType: 'cmd',
},
{
id: 'cmd',
@@ -59,6 +60,7 @@ export class WindowsStockShellsProvider extends WindowsBaseShellProvider {
command: 'cmd.exe',
env: {},
icon: require('../icons/cmd.svg'),
shellType: 'cmd',
},
{
id: 'powershell',
@@ -67,6 +69,7 @@ export class WindowsStockShellsProvider extends WindowsBaseShellProvider {
args: ['-nologo'],
icon: require('../icons/powershell.svg'),
env: this.getEnvironment(),
shellType: 'powershell',
},
]
}
+3
View File
@@ -67,6 +67,7 @@ export class WSLShellProvider extends ShellProvider {
TERM: 'xterm-color',
COLORTERM: 'truecolor',
},
shellType: 'unix',
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
icon: wslIconMap[defaultDistKey.DistributionName.value] ?? wslIconMap.Linux,
}
@@ -85,6 +86,7 @@ export class WSLShellProvider extends ShellProvider {
TERM: 'xterm-color',
COLORTERM: 'truecolor',
},
shellType: 'unix',
}]
} else {
return []
@@ -109,6 +111,7 @@ export class WSLShellProvider extends ShellProvider {
TERM: 'xterm-color',
COLORTERM: 'truecolor',
},
shellType: 'unix',
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
icon: wslIconMap[name] ?? wslIconMap.Linux,
}
+5
View File
@@ -1,5 +1,7 @@
import { BaseTerminalProfile } from 'tabby-terminal'
export type ShellType = 'unix' | 'powershell' | 'cmd'
export interface Shell {
id: string
name: string
@@ -20,6 +22,8 @@ export interface Shell {
*/
icon?: string
shellType?: ShellType
hidden?: boolean
}
@@ -39,6 +43,7 @@ export interface SessionOptions {
env: Record<string, string>
width: number | null
height: number | null
shellType: ShellType | null
pauseAfterExit: boolean
runAsAdministrator: boolean
}
+2
View File
@@ -22,6 +22,7 @@ export class LocalProfilesService extends ProfileProvider<LocalProfile> {
},
width: null,
height: null,
shellType: null,
pauseAfterExit: false,
runAsAdministrator: false,
},
@@ -82,6 +83,7 @@ export class LocalProfilesService extends ProfileProvider<LocalProfile> {
args: shell.args ?? [],
env: shell.env,
cwd: shell.cwd ?? null,
shellType: shell.shellType ?? null,
}
}