Skip to main content

code_it_later_rs/
lib.rs

1#![feature(never_type)]
2#![feature(exit_status_error)]
3
4use std::collections::HashSet;
5
6use datatypes::Bread;
7
8pub mod args;
9pub mod config;
10pub mod datatypes;
11pub mod fs_operation;
12
13use datatypes::*;
14
15pub fn prompt(mut conf: config::Config) -> Result<Option<HashSet<String>>, String> {
16    if conf.delete {
17        // only delete is true gonna triger the prompt
18        conf.delete = false;
19        let yes = conf.yes;
20        let breads = fs_operation::handle_files(conf).collect::<Vec<_>>();
21        let mut files_changed = None;
22        if yes {
23            let mut cache = HashSet::new();
24            for b in breads {
25                cache.insert(
26                    fs_operation::delete_the_crumbs(b).map_err(|e| e.to_string())?,
27                );
28            }
29            if !cache.is_empty() {
30                files_changed = Some(cache)
31            };
32        } else {
33            let mut rl = rustyline::Editor::<()>::new();
34            loop {
35                breads.iter().for_each(|b| println!("{}", b));
36                match rl.readline("Are you sure you want to delete all crumbs? (y/n/s/i): ") {
37                    Ok(s) => match s.as_str() {
38                        "y" => {
39                            let mut cache = HashSet::new();
40                            for b in breads {
41                                cache.insert(
42                                    fs_operation::delete_the_crumbs(b).map_err(|e| e.to_string())?,
43                                );
44                            }
45                            if !cache.is_empty() {
46                                files_changed = Some(cache)
47                            };
48                        }
49                        "n" => (), // do nothing
50                        "s" => continue,
51                        "i" => {
52                            files_changed = Some(prompt_bread(breads.into_iter(), &mut rl, "delete")?)
53                        }
54                        _ => return Err("I don't understand, please give y/n/s/i".to_string()),
55                    },
56                    Err(e) => return Err(format!("error in prompt readline {}", e.to_string())),
57                }
58                break;
59            }
60        }
61        Ok(files_changed)
62    } else if conf.restore {
63        let yes = conf.yes;
64        let breads = fs_operation::handle_files(conf).collect::<Vec<_>>();
65        let mut files_changed = None;
66        if yes {
67            let mut cache = HashSet::new();
68            for b in breads {
69                cache.insert(
70                    fs_operation::restore_the_crumb(b).map_err(|e| e.to_string())?,
71                );
72            }
73            if !cache.is_empty() {
74                files_changed = Some(cache)
75            };
76        } else {
77            let mut rl = rustyline::Editor::<()>::new();
78            loop {
79                breads.iter().for_each(|b| println!("{}", b));
80                match rl.readline("Are you sure you want to restore all crumbs? (y/n/s/i): ") {
81                    Ok(s) => match s.as_str() {
82                        "y" => {
83                            let mut cache = HashSet::new();
84                            for b in breads {
85                                cache.insert(
86                                    fs_operation::restore_the_crumb(b).map_err(|e| e.to_string())?,
87                                );
88                            }
89                            if !cache.is_empty() {
90                                files_changed = Some(cache)
91                            };
92                        }
93                        "n" => (), // do nothing
94                        "s" => continue,
95                        "i" => {
96                            files_changed = Some(prompt_bread(breads.into_iter(), &mut rl, "restore")?)
97                        }
98                        _ => return Err("I don't understand, please give y/n/s/i".to_string()),
99                    },
100                    Err(e) => return Err(format!("error in prompt readline {}", e.to_string())),
101                }
102                break;
103            }
104        }
105        Ok(files_changed)
106    } else {
107        match conf.output {
108            config::OutputFormat::None => {
109                fs_operation::handle_files(conf).for_each(|b| println!("{}", b))
110            }
111            config::OutputFormat::Json => {
112                println!(
113                    "{}",
114                    serde_json::to_string(&fs_operation::handle_files(conf).collect::<Vec<_>>())
115                        .map_err(|e| e.to_string())?
116                )
117            }
118            config::OutputFormat::List => fs_operation::handle_files(conf).for_each(|b| {
119                b.crumbs
120                    .iter()
121                    .for_each(|crumb| println!("{}:{}", b.file_path, crumb.list_format()))
122            }),
123            config::OutputFormat::Range => fs_operation::handle_files(conf).for_each(|b| {
124                b.crumbs.iter().for_each(|crumb| {
125                    println!(
126                        r#"File path: {}
127
128The mark:
129{}
130
131Context around:
132{}
133=======================
134"#,
135                        b.file_path,
136                        crumb,
137                        crumb.range_format()
138                    )
139                })
140            }),
141        }
142        Ok(None)
143    }
144}
145
146fn prompt_bread(
147    breads: impl Iterator<Item = Bread>,
148    rl: &mut rustyline::Editor<()>,
149    op: &str,
150) -> Result<HashSet<String>, String> {
151    let mut files_changed = HashSet::new();
152    for b in breads {
153        loop {
154            // incase need show again
155            println!("{}", b);
156            match rl.readline(&format!(
157                "Are you sure you want to {} this bread {}? (y/n/s/i): ",
158                op, b.file_path
159            )) {
160                Ok(s) => match s.as_str() {
161                    "y" => match op {
162                        "delete" => {
163                            files_changed.insert(
164                                fs_operation::delete_the_crumbs(b).map_err(|e| e.to_string())?,
165                            );
166                        }
167                        "restore" => {
168                            files_changed.insert(
169                                fs_operation::restore_the_crumb(b).map_err(|e| e.to_string())?,
170                            );
171                        }
172                        _ => (),
173                    },
174                    "n" => {}
175                    "s" => {
176                        continue;
177                    }
178                    "i" => {
179                        let go_to_handle = prompt_crumbs(b.crumbs.iter(), rl, op)?;
180                        if go_to_handle.len() != 0 {
181                            match op {
182                                "delete" => {
183                                    files_changed.insert(
184                                        fs_operation::delete_the_crumbs_on_special_index(
185                                            b,
186                                            go_to_handle,
187                                        )
188                                        .map_err(|e| e.to_string())?,
189                                    );
190                                }
191                                "restore" => {
192                                    files_changed.insert(
193                                        fs_operation::restore_the_crumb_on_special_index(
194                                            b,
195                                            go_to_handle,
196                                        )
197                                        .map_err(|e| e.to_string())?,
198                                    );
199                                }
200                                _ => (),
201                            }
202                        }
203                    }
204                    _ => {
205                        println!("I don't understand, please give y/n/s/i");
206                    }
207                },
208                Err(e) => return Err(e.to_string()),
209            }
210            break;
211        }
212    }
213    Ok(files_changed)
214}
215
216fn prompt_crumbs<'a>(
217    crumbs: impl Iterator<Item = &'a Crumb>,
218    rl: &mut rustyline::Editor<()>,
219    op: &str,
220) -> Result<HashSet<usize>, String> {
221    let mut going_to_handle_crumbs_indexes = HashSet::new();
222    for (ind, c) in crumbs.enumerate() {
223        loop {
224            println!("{}", c);
225            match rl.readline(&format!(
226                "Are you sure you want to {} this crumb? (y/n/s): ",
227                op
228            )) {
229                Ok(s) => match s.as_str() {
230                    "y" => {
231                        going_to_handle_crumbs_indexes.insert(ind);
232                    }
233                    "n" => {}
234                    "s" => {
235                        continue;
236                    }
237                    _ => {
238                        println!("I don't understand, please give y/n/s");
239                    }
240                },
241                Err(e) => return Err(e.to_string()),
242            }
243            break;
244        }
245    }
246    Ok(going_to_handle_crumbs_indexes)
247}