Fix clipboard actions over ssh
This commit is contained in:
@@ -8,6 +8,36 @@ import { promisify } from "util";
|
|||||||
|
|
||||||
const execAsync = promisify(exec);
|
const execAsync = promisify(exec);
|
||||||
|
|
||||||
|
// Define a list of clipboard methods with their platform and command.
|
||||||
|
// The platform is a function that returns true if the method is available on the current platform.
|
||||||
|
// The command is a function that returns a promise that resolves to the result of the command.
|
||||||
|
const clipboardMethods = {
|
||||||
|
pbCopy: {
|
||||||
|
platform: (platform: string) => platform === 'darwin',
|
||||||
|
command: async (text: string) => execAsync(`printf '%s' '${text}' | pbcopy`),
|
||||||
|
},
|
||||||
|
xclip: {
|
||||||
|
platform: (platform: string) => platform === 'linux',
|
||||||
|
command: async (text: string) => execAsync(`printf '%s' '${text}' | xclip -selection clipboard`),
|
||||||
|
},
|
||||||
|
xsel: {
|
||||||
|
platform: (platform: string) => platform === 'linux',
|
||||||
|
command: async (text: string) => execAsync(`printf '%s' '${text}' | xsel --clipboard --input`),
|
||||||
|
},
|
||||||
|
ssh: {
|
||||||
|
platform: (platform: string) => platform === 'linux',
|
||||||
|
command: async (text: string) => process.stdout.write(`\x1b]52;c;${Buffer.from(text, 'utf-8').toString('base64')}\x07`),
|
||||||
|
},
|
||||||
|
clip: {
|
||||||
|
platform: (platform: string) => platform === 'windows',
|
||||||
|
command: async (text: string) => execAsync(`echo|set /p="${text}" | clip`),
|
||||||
|
},
|
||||||
|
clipboardy: {
|
||||||
|
platform: (platform: string) => platform === 'windows',
|
||||||
|
command: async (text: string) => clipboardy.writeSync(text),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to copy text to clipboard using multiple methods.
|
* Attempts to copy text to clipboard using multiple methods.
|
||||||
* Tries native commands first (most reliable), then clipboardy as fallback.
|
* Tries native commands first (most reliable), then clipboardy as fallback.
|
||||||
@@ -21,46 +51,25 @@ export async function copyToClipboard(text: string): Promise<void> {
|
|||||||
// Escape the text for shell commands
|
// Escape the text for shell commands
|
||||||
const escapedText = text.replace(/'/g, "'\\''");
|
const escapedText = text.replace(/'/g, "'\\''");
|
||||||
|
|
||||||
// Try native commands first - they're more reliable
|
const availableMethods = Object.values(clipboardMethods).filter(method => method.platform(platform));
|
||||||
try {
|
|
||||||
if (platform === "darwin") {
|
|
||||||
// macOS - use pbcopy directly
|
|
||||||
await execAsync(`printf '%s' '${escapedText}' | pbcopy`);
|
|
||||||
return;
|
|
||||||
} else if (platform === "linux") {
|
|
||||||
// Linux - try xclip, then xsel
|
|
||||||
try {
|
|
||||||
await execAsync(
|
|
||||||
`printf '%s' '${escapedText}' | xclip -selection clipboard`,
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
} catch {
|
|
||||||
try {
|
|
||||||
await execAsync(
|
|
||||||
`printf '%s' '${escapedText}' | xsel --clipboard --input`,
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
} catch {
|
|
||||||
// Fall through to clipboardy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (platform === "win32") {
|
|
||||||
// Windows - use clip.exe
|
|
||||||
await execAsync(`echo|set /p="${text}" | clip`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
// Native command failed, try clipboardy
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback to clipboardy
|
const errors: Error[] = [];
|
||||||
|
|
||||||
|
for (const method of availableMethods) {
|
||||||
try {
|
try {
|
||||||
clipboardy.writeSync(text);
|
if (method.platform(platform)) {
|
||||||
|
await method.command(escapedText);
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
} catch {
|
} catch(error) {
|
||||||
// clipboardy also failed
|
if (error instanceof Error) {
|
||||||
|
errors.push(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// All methods failed
|
// All methods failed
|
||||||
throw new Error(`Clipboard not available. Install xclip or xsel on Linux.`);
|
throw new Error(`Clipboard not available. ${errors.map(error => error.message).join('\n')}`);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user