#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ClipboardResult {
Success,
Error(String),
NotAvailable,
}
impl ClipboardResult {
pub fn is_success(&self) -> bool {
matches!(self, ClipboardResult::Success)
}
pub fn is_error(&self) -> bool {
matches!(self, ClipboardResult::Error(_))
}
pub fn is_not_available(&self) -> bool {
matches!(self, ClipboardResult::NotAvailable)
}
pub fn error_message(&self) -> Option<&str> {
match self {
ClipboardResult::Error(msg) => Some(msg),
_ => None,
}
}
}
impl std::fmt::Display for ClipboardResult {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ClipboardResult::Success => write!(f, "Success"),
ClipboardResult::Error(e) => write!(f, "Error: {}", e),
ClipboardResult::NotAvailable => write!(f, "Clipboard not available"),
}
}
}
#[cfg(feature = "clipboard")]
pub fn copy_to_clipboard(text: &str) -> ClipboardResult {
match arboard::Clipboard::new() {
Ok(mut clipboard) => match clipboard.set_text(text) {
Ok(()) => ClipboardResult::Success,
Err(e) => ClipboardResult::Error(e.to_string()),
},
Err(e) => ClipboardResult::Error(format!("Failed to access clipboard: {}", e)),
}
}
#[cfg(not(feature = "clipboard"))]
pub fn copy_to_clipboard(_text: &str) -> ClipboardResult {
ClipboardResult::NotAvailable
}
#[cfg(feature = "clipboard")]
pub fn get_from_clipboard() -> Result<String, ClipboardResult> {
match arboard::Clipboard::new() {
Ok(mut clipboard) => match clipboard.get_text() {
Ok(text) => Ok(text),
Err(e) => Err(ClipboardResult::Error(e.to_string())),
},
Err(e) => Err(ClipboardResult::Error(format!(
"Failed to access clipboard: {}",
e
))),
}
}
#[cfg(not(feature = "clipboard"))]
pub fn get_from_clipboard() -> Result<String, ClipboardResult> {
Err(ClipboardResult::NotAvailable)
}
#[cfg(feature = "clipboard")]
pub fn is_clipboard_available() -> bool {
arboard::Clipboard::new().is_ok()
}
#[cfg(not(feature = "clipboard"))]
pub fn is_clipboard_available() -> bool {
false
}
pub fn copy_lines_to_clipboard<'a, I>(lines: I) -> ClipboardResult
where
I: Iterator<Item = &'a str>,
{
let text: String = lines.collect::<Vec<_>>().join("\n");
copy_to_clipboard(&text)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_clipboard_result_is_success() {
assert!(ClipboardResult::Success.is_success());
assert!(!ClipboardResult::Error("test".into()).is_success());
assert!(!ClipboardResult::NotAvailable.is_success());
}
#[test]
fn test_clipboard_result_is_error() {
assert!(!ClipboardResult::Success.is_error());
assert!(ClipboardResult::Error("test".into()).is_error());
assert!(!ClipboardResult::NotAvailable.is_error());
}
#[test]
fn test_clipboard_result_is_not_available() {
assert!(!ClipboardResult::Success.is_not_available());
assert!(!ClipboardResult::Error("test".into()).is_not_available());
assert!(ClipboardResult::NotAvailable.is_not_available());
}
#[test]
fn test_clipboard_result_error_message() {
assert_eq!(ClipboardResult::Success.error_message(), None);
assert_eq!(
ClipboardResult::Error("test".into()).error_message(),
Some("test")
);
assert_eq!(ClipboardResult::NotAvailable.error_message(), None);
}
#[test]
fn test_clipboard_result_display() {
assert_eq!(format!("{}", ClipboardResult::Success), "Success");
assert_eq!(
format!("{}", ClipboardResult::Error("oops".into())),
"Error: oops"
);
assert_eq!(
format!("{}", ClipboardResult::NotAvailable),
"Clipboard not available"
);
}
#[cfg(not(feature = "clipboard"))]
#[test]
fn test_clipboard_not_available_without_feature() {
assert!(!is_clipboard_available());
assert!(copy_to_clipboard("test").is_not_available());
assert!(get_from_clipboard().is_err());
}
#[test]
fn test_copy_lines_to_clipboard() {
let lines = vec!["a", "b", "c"];
let _ = copy_lines_to_clipboard(lines.iter().copied());
}
}