pocket_cli/utils/
clipboard.rs1use anyhow::{Result, anyhow};
2use std::process::{Command, Stdio};
3
4pub fn read_clipboard() -> Result<String> {
8 #[cfg(target_os = "macos")]
9 {
10 let output = Command::new("pbpaste")
11 .output()
12 .map_err(|_| anyhow!("Failed to access clipboard. Make sure 'pbpaste' is available."))?;
13
14 if !output.status.success() {
15 return Err(anyhow!("Failed to read from clipboard"));
16 }
17
18 Ok(String::from_utf8_lossy(&output.stdout).trim().to_string())
19 }
20
21 #[cfg(target_os = "windows")]
22 {
23 let output = Command::new("powershell.exe")
24 .args(["-command", "Get-Clipboard"])
25 .output()
26 .map_err(|_| anyhow!("Failed to access clipboard. Make sure PowerShell is available."))?;
27
28 if !output.status.success() {
29 return Err(anyhow!("Failed to read from clipboard"));
30 }
31
32 Ok(String::from_utf8_lossy(&output.stdout).trim().to_string())
33 }
34
35 #[cfg(all(unix, not(target_os = "macos")))]
36 {
37 let xclip_result = Command::new("xclip")
39 .args(["-selection", "clipboard", "-o"])
40 .output();
41
42 if let Ok(output) = xclip_result {
44 if output.status.success() {
45 return Ok(String::from_utf8_lossy(&output.stdout).trim().to_string());
46 }
47 }
48
49 let wl_paste_result = Command::new("wl-paste")
51 .output();
52
53 if let Ok(output) = wl_paste_result {
55 if output.status.success() {
56 return Ok(String::from_utf8_lossy(&output.stdout).trim().to_string());
57 }
58 }
59
60 Err(anyhow!("Failed to access clipboard. Please install xclip (for X11) or wl-paste (for Wayland)."))
62 }
63
64 #[cfg(not(any(target_os = "macos", target_os = "windows", all(unix, not(target_os = "macos")))))]
66 {
67 Err(anyhow!("Clipboard functionality is not supported on this platform"))
68 }
69}
70
71pub fn write_clipboard(content: &str) -> Result<()> {
75 #[cfg(target_os = "macos")]
76 {
77 let mut child = Command::new("pbcopy")
78 .stdin(Stdio::piped())
79 .spawn()
80 .map_err(|_| anyhow!("Failed to access clipboard. Make sure 'pbcopy' is available."))?;
81
82 if let Some(mut stdin) = child.stdin.take() {
83 use std::io::Write;
84 stdin.write_all(content.as_bytes())?;
85 }
86
87 let status = child.wait()?;
88 if !status.success() {
89 return Err(anyhow!("Failed to write to clipboard"));
90 }
91
92 Ok(())
93 }
94
95 #[cfg(target_os = "windows")]
96 {
97 let mut child = Command::new("powershell.exe")
99 .args(["-command", "Set-Clipboard -Value $input"])
100 .stdin(Stdio::piped())
101 .spawn()
102 .map_err(|_| anyhow!("Failed to access clipboard. Make sure PowerShell is available."))?;
103
104 if let Some(mut stdin) = child.stdin.take() {
105 use std::io::Write;
106 stdin.write_all(content.as_bytes())?;
107 }
108
109 let status = child.wait()?;
110 if !status.success() {
111 return Err(anyhow!("Failed to write to clipboard"));
112 }
113
114 Ok(())
115 }
116
117 #[cfg(all(unix, not(target_os = "macos")))]
118 {
119 let mut xclip_child = Command::new("xclip")
121 .args(["-selection", "clipboard"])
122 .stdin(Stdio::piped())
123 .spawn();
124
125 if let Ok(mut child) = xclip_child {
126 if let Some(mut stdin) = child.stdin.take() {
127 use std::io::Write;
128 stdin.write_all(content.as_bytes())?;
129 }
130
131 let status = child.wait()?;
132 if status.success() {
133 return Ok(());
134 }
135 }
136
137 let mut wl_copy_child = Command::new("wl-copy")
139 .stdin(Stdio::piped())
140 .spawn();
141
142 if let Ok(mut child) = wl_copy_child {
143 if let Some(mut stdin) = child.stdin.take() {
144 use std::io::Write;
145 stdin.write_all(content.as_bytes())?;
146 }
147
148 let status = child.wait()?;
149 if status.success() {
150 return Ok(());
151 }
152 }
153
154 Err(anyhow!("Failed to access clipboard. Please install xclip (for X11) or wl-copy (for Wayland)."))
156 }
157
158 #[cfg(not(any(target_os = "macos", target_os = "windows", all(unix, not(target_os = "macos")))))]
160 {
161 Err(anyhow!("Clipboard functionality is not supported on this platform"))
162 }
163}
164
165#[cfg(test)]
166mod tests {
167 use super::*;
168
169 #[test]
170 #[ignore] fn test_clipboard_write_read() {
172 let test_content = "Test clipboard content";
173
174 write_clipboard(test_content).expect("Failed to write to clipboard");
176
177 let read_content = read_clipboard().expect("Failed to read from clipboard");
179
180 assert_eq!(read_content, test_content);
181 }
182}