bernardo-tui 0.2.7

A keyboard-only, distraction-free TUI widget library
Documentation
use std::sync::{Arc, RwLock};

use log::error;

const EMPTY_STRING: String = String::new();

pub type ClipboardRef = Arc<Box<dyn Clipboard>>;

pub trait Clipboard: Sync + Send {
    fn get(&self) -> String;
    fn set(&self, s: String) -> bool;
}

pub fn get_me_some_clipboard() -> ClipboardRef {
    match DefaultClipboard::new() {
        Some(dc) => Arc::new(Box::new(dc)),
        None => {
            error!("using failsafe fake clipboard");
            Arc::new(Box::new(FakeClipboard::default()))
        }
    }
}

pub fn get_me_fake_clipboard() -> ClipboardRef {
    Arc::new(Box::new(FakeClipboard::default()))
}

struct DefaultClipboard {
    clipboard: RwLock<arboard::Clipboard>,
}

impl DefaultClipboard {
    pub fn new() -> Option<Self> {
        match arboard::Clipboard::new() {
            Ok(c) => Some(DefaultClipboard { clipboard: RwLock::new(c) }),
            Err(e) => {
                error!("failed acquiring clipboard: {:?}", e);
                None
            }
        }
    }
}

impl Clipboard for DefaultClipboard {
    fn get(&self) -> String {
        match self.clipboard.try_write() {
            Ok(mut clipboard) => match clipboard.get_text() {
                Ok(text) => text,
                Err(e) => {
                    error!("error getting text from clipboard: {:?}", e);
                    EMPTY_STRING
                }
            },
            Err(e) => {
                error!("failed acquiring clipboard lock: {:?}", e);
                EMPTY_STRING
            }
        }
    }

    fn set(&self, contents: String) -> bool {
        match self.clipboard.try_write() {
            Ok(mut clipboard) => clipboard
                .set_text(contents)
                .map_err(|e| error!("error setting clipboard contents: {:?}", e))
                .is_ok(),
            Err(e) => {
                error!("failed acquiring clipboard lock: {:?}", e);
                false
            }
        }
    }
}

struct FakeClipboard {
    contents: RwLock<String>,
}

impl Default for FakeClipboard {
    fn default() -> Self {
        FakeClipboard {
            contents: RwLock::new(EMPTY_STRING),
        }
    }
}

impl Clipboard for FakeClipboard {
    fn get(&self) -> String {
        match self.contents.try_read() {
            Ok(clipboard) => clipboard.clone(),
            Err(e) => {
                error!("failed acquiring clipboard lock: {:?}", e);
                EMPTY_STRING
            }
        }
    }

    fn set(&self, contents: String) -> bool {
        match self.contents.try_write() {
            Ok(mut cr) => {
                *cr = contents;
                true
            }
            Err(e) => {
                error!("failed acquiring clipboard lock: {:?}", e);
                false
            }
        }
    }
}