Support dragging source control files into terminals (#172)

This commit is contained in:
Jinjing 2026-03-28 13:37:52 -07:00 committed by GitHub
parent dc8e6d007c
commit d4fc4bef19
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 49 additions and 1 deletions

View File

@ -238,6 +238,12 @@ export default function SourceControl(): React.JSX.Element {
<div
key={`${area}:${entry.path}`}
className="group flex items-center gap-1 px-3 py-0.5 hover:bg-accent/40 transition-colors cursor-pointer"
draggable
onDragStart={(e) => {
const absolutePath = joinPath(worktreePath, entry.path)
e.dataTransfer.setData('text/x-orca-file-path', absolutePath)
e.dataTransfer.effectAllowed = 'copy'
}}
onClick={() => handleOpenDiff(entry)}
>
<StatusIcon

View File

@ -0,0 +1,30 @@
import { describe, expect, it } from 'vitest'
import { shellEscapePath } from './pane-helpers'
describe('shellEscapePath', () => {
it('keeps safe POSIX paths unquoted', () => {
expect(shellEscapePath('/tmp/file.txt', 'Macintosh')).toBe('/tmp/file.txt')
})
it('single-quotes POSIX paths with shell-special characters', () => {
expect(shellEscapePath("/tmp/it's here.txt", 'Linux')).toBe("'/tmp/it'\\''s here.txt'")
})
it('keeps safe Windows paths unquoted', () => {
expect(shellEscapePath('C:\\Users\\orca\\file.txt', 'Windows')).toBe(
'C:\\Users\\orca\\file.txt'
)
})
it('double-quotes Windows paths with spaces', () => {
expect(shellEscapePath('C:\\Users\\orca\\my file.txt', 'Windows')).toBe(
'"C:\\Users\\orca\\my file.txt"'
)
})
it('double-quotes Windows paths with cmd separators', () => {
expect(shellEscapePath('C:\\Users\\orca\\a&b.txt', 'Windows')).toBe(
'"C:\\Users\\orca\\a&b.txt"'
)
})
})

View File

@ -21,9 +21,21 @@ export function fitAndFocusPanes(manager: PaneManager): void {
focusActivePane(manager)
}
export function shellEscapePath(path: string): string {
function isWindowsUserAgent(userAgent: string): boolean {
return userAgent.includes('Windows')
}
export function shellEscapePath(
path: string,
userAgent: string = typeof navigator === 'undefined' ? '' : navigator.userAgent
): string {
if (isWindowsUserAgent(userAgent)) {
return /^[a-zA-Z0-9_./@:\\-]+$/.test(path) ? path : `"${path}"`
}
if (/^[a-zA-Z0-9_./@:-]+$/.test(path)) {
return path
}
return `'${path.replace(/'/g, "'\\''")}'`
}