summaryrefslogtreecommitdiffstats
path: root/src/clipboard.rs
blob: 8b56e3e9a9a8ee97fbf99aba034d090120442554 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
use anyhow::{anyhow, Result};
#[cfg(target_os = "linux")]
use std::ffi::OsStr;
use std::io::Write;
use std::process::{Command, Stdio};

fn execute_copy_command(command: Command, text: &str) -> Result<()> {
    let mut command = command;

    let mut process = command
        .stdin(Stdio::piped())
        .stdout(Stdio::null())
        .spawn()
        .map_err(|e| anyhow!("`{:?}`: {}", command, e))?;

    process
        .stdin
        .as_mut()
        .ok_or_else(|| anyhow!("`{:?}`", command))?
        .write_all(text.as_bytes())
        .map_err(|e| anyhow!("`{:?}`: {}", command, e))?;

    process
        .wait()
        .map_err(|e| anyhow!("`{:?}`: {}", command, e))?;

    Ok(())
}

#[cfg(target_os = "linux")]
fn gen_command(
    path: impl AsRef<OsStr>,
    xclip_syntax: bool,
) -> Command {
    let mut c = Command::new(path);
    if xclip_syntax {
        c.arg("-selection");
        c.arg("clipboard");
    } else {
        c.arg("--clipboard");
    }
    c
}

#[cfg(target_os = "linux")]
pub fn copy_string(string: &str) -> Result<()> {
    use std::path::PathBuf;
    use which::which;
    let (path, xclip_syntax) = which("xclip").ok().map_or_else(
        || {
            (
                which("xsel")
                    .ok()
                    .unwrap_or_else(|| PathBuf::from("xsel")),
                false,
            )
        },
        |path| (path, true),
    );

    let cmd = gen_command(path, xclip_syntax);
    execute_copy_command(cmd, string)
}

#[cfg(target_os = "macos")]
pub fn copy_string(string: &str) -> Result<()> {
    execute_copy_command(Command::new("pbcopy"), string)
}

#[cfg(windows)]
pub fn copy_string(string: &str) -> Result<()> {
    execute_copy_command(Command::new("clip"), string)
}