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