fix: clipboard auto-detect had no macOS/Windows fallback, failed silently

copy_auto only ever tried wl-copy/xclip, so on macOS or Windows it
always returned false with no clipboard tool attempted. Added
pbcopy/clip fallbacks per-OS. Also, the detail-pane 'y'/'u' handlers
showed a status message only on success — a failed copy (no tool
found) looked like nothing happened at all; both now report the
outcome either way.
This commit is contained in:
dualfroz committed 2026-07-23 07:25:08 +02:00
1 parent cd4e8e92ea
commit edf4bd34bf
2 files changed
+26 -5

No files matched your search

+10 -2
View File
@@ -495,11 +495,19 @@ pub fn handle_key(code: KeyCode, st: &mut St) {
KeyCode::Char('o') => { st.run_action = Some(106); } KeyCode::Char('o') => { st.run_action = Some(106); }
KeyCode::Char('y') => { KeyCode::Char('y') => {
let path = st.summary.path.to_string_lossy().to_string(); let path = st.summary.path.to_string_lossy().to_string();
if copy_to_clipboard(&path) { st.status_msg = Some("Path copied!".into()); } st.status_msg = Some(if copy_to_clipboard(&path) {
"Path copied!".into()
} else {
format!("No clipboard tool found — path: {}", path)
});
} }
KeyCode::Char('u') => { KeyCode::Char('u') => {
if let Some(ref url) = st.remote_url_str.clone() { if let Some(ref url) = st.remote_url_str.clone() {
if copy_to_clipboard(url) { st.status_msg = Some("URL copied!".into()); } st.status_msg = Some(if copy_to_clipboard(url) {
"URL copied!".into()
} else {
format!("No clipboard tool found — URL: {}", url)
});
} }
} }
KeyCode::Char('g') => { KeyCode::Char('g') => {
+16 -3
View File
@@ -17,11 +17,24 @@ pub fn copy_to_clipboard(text: &str, cmd: &str) -> bool {
child.wait().map(|s| s.success()).unwrap_or(false) child.wait().map(|s| s.success()).unwrap_or(false)
} }
/// Copy text by auto-detecting the available clipboard tool (wl-copy or xclip). /// Copy text by auto-detecting the available clipboard tool: `wl-copy`/`xclip`
/// on Linux, `pbcopy` on macOS, `clip` on Windows. Tries every candidate for
/// the current OS in order and returns on the first one that actually
/// launches and exits successfully — callers should surface a status message
/// on `false` (nothing copied) rather than assume success, since on Linux
/// without either tool installed, or on an unexpected platform, this is a
/// real "no-op" outcome the user needs to know about.
pub fn copy_auto(text: &str) -> bool { pub fn copy_auto(text: &str) -> bool {
for (cmd, args) in [("wl-copy", &[][..]), ("xclip", &["-selection", "clipboard"][..])] { #[cfg(target_os = "macos")]
let candidates: &[(&str, &[&str])] = &[("pbcopy", &[])];
#[cfg(target_os = "windows")]
let candidates: &[(&str, &[&str])] = &[("clip", &[])];
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
let candidates: &[(&str, &[&str])] = &[("wl-copy", &[]), ("xclip", &["-selection", "clipboard"])];
for (cmd, args) in candidates {
if let Ok(mut child) = std::process::Command::new(cmd) if let Ok(mut child) = std::process::Command::new(cmd)
.args(args).stdin(std::process::Stdio::piped()).spawn() { .args(*args).stdin(std::process::Stdio::piped()).spawn() {
if let Some(mut stdin) = child.stdin.take() { let _ = stdin.write_all(text.as_bytes()); } if let Some(mut stdin) = child.stdin.take() { let _ = stdin.write_all(text.as_bytes()); }
if child.wait().map(|s| s.success()).unwrap_or(false) { return true; } if child.wait().map(|s| s.success()).unwrap_or(false) { return true; }
} }