Fix clipboard actions over ssh
This commit is contained in:
@@ -8,6 +8,36 @@ import { promisify } from "util";
|
||||
|
||||
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.
|
||||
* 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
|
||||
const escapedText = text.replace(/'/g, "'\\''");
|
||||
|
||||
// Try native commands first - they're more reliable
|
||||
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
|
||||
}
|
||||
const availableMethods = Object.values(clipboardMethods).filter(method => method.platform(platform));
|
||||
|
||||
// Fallback to clipboardy
|
||||
const errors: Error[] = [];
|
||||
|
||||
for (const method of availableMethods) {
|
||||
try {
|
||||
clipboardy.writeSync(text);
|
||||
if (method.platform(platform)) {
|
||||
await method.command(escapedText);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
return;
|
||||
} catch {
|
||||
// clipboardy also failed
|
||||
} catch(error) {
|
||||
if (error instanceof Error) {
|
||||
errors.push(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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