use crate::error::{PadzError, Result};
use std::process::Command;
pub fn copy_to_clipboard(text: &str) -> Result<()> {
#[cfg(target_os = "macos")]
{
copy_macos(text)
}
#[cfg(target_os = "linux")]
{
copy_linux(text)
}
#[cfg(target_os = "windows")]
{
copy_windows(text)
}
#[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))]
{
Err(PadzError::Api(
"Clipboard not supported on this platform".to_string(),
))
}
}
#[cfg(target_os = "macos")]
fn copy_macos(text: &str) -> Result<()> {
use std::io::Write;
use std::process::Stdio;
let mut child = Command::new("pbcopy")
.stdin(Stdio::piped())
.spawn()
.map_err(|e| PadzError::Api(format!("Failed to spawn pbcopy: {}", e)))?;
if let Some(mut stdin) = child.stdin.take() {
stdin
.write_all(text.as_bytes())
.map_err(|e| PadzError::Api(format!("Failed to write to pbcopy: {}", e)))?;
}
let status = child
.wait()
.map_err(|e| PadzError::Api(format!("Failed to wait for pbcopy: {}", e)))?;
if status.success() {
Ok(())
} else {
Err(PadzError::Api("pbcopy exited with error".to_string()))
}
}
#[cfg(target_os = "linux")]
fn copy_linux(text: &str) -> Result<()> {
use std::io::Write;
use std::process::Stdio;
let result = Command::new("xclip")
.args(["-selection", "clipboard"])
.stdin(Stdio::piped())
.spawn();
let mut child = match result {
Ok(child) => child,
Err(_) => {
Command::new("xsel")
.args(["--clipboard", "--input"])
.stdin(Stdio::piped())
.spawn()
.map_err(|e| {
PadzError::Api(format!(
"Failed to spawn xclip or xsel: {}. Install xclip or xsel.",
e
))
})?
}
};
if let Some(mut stdin) = child.stdin.take() {
stdin
.write_all(text.as_bytes())
.map_err(|e| PadzError::Api(format!("Failed to write to clipboard: {}", e)))?;
}
let status = child
.wait()
.map_err(|e| PadzError::Api(format!("Failed to wait for clipboard command: {}", e)))?;
if status.success() {
Ok(())
} else {
Err(PadzError::Api(
"Clipboard command exited with error".to_string(),
))
}
}
#[cfg(target_os = "windows")]
fn copy_windows(text: &str) -> Result<()> {
use std::io::Write;
use std::process::Stdio;
let mut child = Command::new("clip")
.stdin(Stdio::piped())
.spawn()
.map_err(|e| PadzError::Api(format!("Failed to spawn clip: {}", e)))?;
if let Some(mut stdin) = child.stdin.take() {
stdin
.write_all(text.as_bytes())
.map_err(|e| PadzError::Api(format!("Failed to write to clip: {}", e)))?;
}
let status = child
.wait()
.map_err(|e| PadzError::Api(format!("Failed to wait for clip: {}", e)))?;
if status.success() {
Ok(())
} else {
Err(PadzError::Api("clip exited with error".to_string()))
}
}
pub fn format_for_clipboard(title: &str, content: &str) -> String {
if content.is_empty() {
format!("{}\n\n", title)
} else {
format!("{}\n\n{}", title, content)
}
}
pub fn get_from_clipboard() -> Result<String> {
#[cfg(target_os = "macos")]
{
get_macos()
}
#[cfg(target_os = "linux")]
{
get_linux()
}
#[cfg(target_os = "windows")]
{
get_windows()
}
#[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))]
{
Err(PadzError::Api(
"Clipboard not supported on this platform".to_string(),
))
}
}
#[cfg(target_os = "macos")]
fn get_macos() -> Result<String> {
let output = Command::new("pbpaste")
.output()
.map_err(|e| PadzError::Api(format!("Failed to execute pbpaste: {}", e)))?;
if output.status.success() {
String::from_utf8(output.stdout)
.map_err(|e| PadzError::Api(format!("Invalid UTF-8 in clipboard: {}", e)))
} else {
Err(PadzError::Api("pbpaste exited with error".to_string()))
}
}
#[cfg(target_os = "linux")]
fn get_linux() -> Result<String> {
let result = Command::new("xclip")
.args(["-selection", "clipboard", "-o"])
.output();
match result {
Ok(output) if output.status.success() => {
return String::from_utf8(output.stdout)
.map_err(|e| PadzError::Api(format!("Invalid UTF-8 in clipboard: {}", e)));
}
_ => {}
}
let result = Command::new("xsel")
.args(["--clipboard", "--output"])
.output();
match result {
Ok(output) if output.status.success() => String::from_utf8(output.stdout)
.map_err(|e| PadzError::Api(format!("Invalid UTF-8 in clipboard: {}", e))),
Ok(_) => Err(PadzError::Api("xsel exited with error".to_string())),
Err(e) => Err(PadzError::Api(format!(
"Failed to execute xclip or xsel: {}. Install xclip or xsel.",
e
))),
}
}
#[cfg(target_os = "windows")]
fn get_windows() -> Result<String> {
let output = Command::new("powershell")
.args(["-command", "Get-Clipboard"])
.output()
.map_err(|e| PadzError::Api(format!("Failed to execute powershell: {}", e)))?;
if output.status.success() {
String::from_utf8(output.stdout)
.map_err(|e| PadzError::Api(format!("Invalid UTF-8 in clipboard: {}", e)))
} else {
Err(PadzError::Api("powershell exited with error".to_string()))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_format_for_clipboard_with_content() {
let result = format_for_clipboard("My Title", "Some content");
assert_eq!(result, "My Title\n\nSome content");
}
#[test]
fn test_format_for_clipboard_empty_content() {
let result = format_for_clipboard("My Title", "");
assert_eq!(result, "My Title\n\n");
}
}