1use anyhow::Result;
2use arboard::Clipboard;
3use std::env;
4use std::fmt::{Display, Error, Formatter};
5use std::fs;
6use std::path::{Path, PathBuf};
7
8pub fn copy(content: &str, register: Option<&str>, verbose: bool) -> Result<()> {
9 match register {
10 Some(filename) => copy_to_file(content, filename, verbose),
11 None => match Clipboard::new() {
12 Ok(mut clipboard) => {
13 clipboard.set_text(content.to_owned())?;
14 if verbose {
15 println!("{}", &content);
16 println!("copied successfully to system clipboard");
17 }
18 Ok(())
19 }
20 Err(_) => copy_to_file(content, "default", verbose),
21 },
22 }
23}
24
25pub fn paste(register: Option<&str>, verbose: bool) -> Result<()> {
26 match register {
27 Some(filename) => {
28 let path = get_register_path(filename)?;
29 paste_from_file(path, verbose)
30 }
31 None => match Clipboard::new() {
32 Ok(mut clipboard) => {
33 match clipboard.get_text() {
34 Ok(text) => print!("{}", text),
35 Err(_) => print!(""),
36 }
37 Ok(())
38 }
39 Err(_) => {
40 let path = get_register_path("default")?;
41 paste_from_file(path, verbose)
42 }
43 },
44 }
45}
46
47fn get_register_path(filename: &str) -> Result<PathBuf> {
48 let mut path = get_register_dir()?;
49 path.push(Path::new(filename).file_name().unwrap()); path.set_extension("txt");
51 Ok(path)
52}
53
54pub fn get_register_dir() -> Result<PathBuf> {
55 let mut path;
56 match env::var("CB_DIR") {
57 Ok(cb_dir_str) => {
58 path = PathBuf::from(cb_dir_str);
59 }
60 Err(_) => {
61 path = env::temp_dir();
62 path.push("crepe-bordeaux");
63 }
64 };
65 if !path.is_dir() {
66 fs::create_dir_all(&path)?;
67 }
68 Ok(path)
69}
70
71fn get_register_paths() -> Result<Vec<PathBuf>> {
72 return Ok(fs::read_dir(get_register_dir()?)?
73 .map(|res| res.map(|e| e.path()))
74 .filter_map(|x| x.ok())
75 .filter(|x| x.is_file())
76 .filter(|x| x.extension().is_some_and(|extension| extension == "txt"))
77 .filter(|x| x.file_stem().is_some_and(|file_stem| !file_stem.is_empty()))
78 .collect::<Vec<PathBuf>>());
79}
80
81fn copy_to_file(content: &str, filename: &str, verbose: bool) -> Result<()> {
82 let path = get_register_path(filename)?;
83 fs::write(path, content)?;
84 if verbose {
85 println!("{}", &content);
86 println!("copied successfully to register: {}", filename);
87 }
88 Ok(())
89}
90
91fn paste_from_file(filepath: PathBuf, verbose: bool) -> Result<()> {
92 match filepath.is_file() {
93 true => {
94 let x = fs::read_to_string(filepath)?;
95 println!("{}", x);
96 Ok(())
97 }
98 false => {
99 if verbose {
100 eprintln!("register not found");
101 } else {
102 print!("");
103 }
104 Ok(())
105 }
106 }
107}
108
109pub fn list() -> Result<()> {
110 let register_paths = get_register_paths()?;
111 let mut register_names = register_paths
112 .iter()
113 .map(|x| String::from(x.file_stem().unwrap().to_str().unwrap()))
114 .collect::<Vec<String>>();
115
116 register_names.sort();
117
118 print!("{}", StringVec(register_names));
119
120 Ok(())
121}
122
123pub fn dump() -> Result<()> {
124 let mut register_paths = get_register_paths()?;
125
126 register_paths.sort();
127
128 let register_contents = register_paths
129 .iter()
130 .filter_map(|path| fs::read_to_string(path).ok())
131 .collect::<Vec<String>>();
132
133 println!("{}", StringVec(register_contents));
134
135 Ok(())
136}
137
138pub fn clear(register: Option<&str>) -> Result<()> {
139 match register {
140 Some(filename) => {
141 let path = get_register_path(filename)?;
142 fs::remove_file(path)?;
143 Ok(())
144 }
145 None => match Clipboard::new() {
146 Ok(mut clipboard) => {
147 clipboard.clear()?;
148 Ok(())
149 }
150 Err(_) => {
151 let path = get_register_path("default")?;
152 fs::remove_file(path)?;
153 Ok(())
154 }
155 },
156 }
157}
158
159pub fn clear_all() -> Result<()> {
160 let register_paths = get_register_paths()?;
161 for path in register_paths {
162 fs::remove_file(path)?;
163 }
164
165 if let Ok(mut clipboard) = Clipboard::new() {
166 clipboard.clear()?;
167 };
168
169 Ok(())
170}
171
172struct StringVec(Vec<String>);
173
174impl Display for StringVec {
175 fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
176 let mut buffer = String::new();
177
178 for item in &self.0 {
179 buffer.push_str(item);
180 buffer.push('\n');
181 }
182
183 write!(f, "{}", buffer.trim())
184 }
185}