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        }
98        Ok(None)
99    }
100}
101
102fn prompt_bread(
103    breads: impl Iterator<Item = Bread>,
104    rl: &mut rustyline::Editor<()>,
105    op: &str,
106) -> Result<HashSet<String>, String> {
107    let mut files_changed = HashSet::new();
108    for b in breads {
109        loop {
110            // incase need show again
111            println!("{}", b);
112            match rl.readline(&format!(
113                "Are you sure you want to {} this bread {}? (y/n/s/i): ",
114                op, b.file_path
115            )) {
116                Ok(s) => match s.as_str() {
117                    "y" => match op {
118                        "delete" => {
119                            files_changed.insert(
120                                fs_operation::delete_the_crumbs(b).map_err(|e| e.to_string())?,
121                            );
122                        }
123                        "restore" => {
124                            files_changed.insert(
125                                fs_operation::restore_the_crumb(b).map_err(|e| e.to_string())?,
126                            );
127                        }
128                        _ => (),
129                    },
130                    "n" => {}
131                    "s" => {
132                        continue;
133                    }
134                    "i" => {
135                        let go_to_handle = prompt_crumbs(b.crumbs.iter(), rl, op)?;
136                        if go_to_handle.len() != 0 {
137                            match op {
138                                "delete" => {
139                                    files_changed.insert(
140                                        fs_operation::delete_the_crumbs_on_special_index(
141                                            b,
142                                            go_to_handle,
143                                        )
144                                        .map_err(|e| e.to_string())?,
145                                    );
146                                }
147                                "restore" => {
148                                    files_changed.insert(
149                                        fs_operation::restore_the_crumb_on_special_index(
150                                            b,
151                                            go_to_handle,
152                                        )
153                                        .map_err(|e| e.to_string())?,
154                                    );
155                                }
156                                _ => (),
157                            }
158                        }
159                    }
160                    _ => {
161                        println!("I don't understand, please give y/n/s/i");
162                    }
163                },
164                Err(e) => return Err(e.to_string()),
165            }
166            break;
167        }
168    }
169    Ok(files_changed)
170}
171
172fn prompt_crumbs<'a>(
173    crumbs: impl Iterator<Item = &'a Crumb>,
174    rl: &mut rustyline::Editor<()>,
175    op: &str,
176) -> Result<HashSet<usize>, String> {
177    let mut going_to_handle_crumbs_indexes = HashSet::new();
178    for (ind, c) in crumbs.enumerate() {
179        loop {
180            println!("{}", c);
181            match rl.readline(&format!(
182                "Are you sure you want to {} this crumb? (y/n/s): ",
183                op
184            )) {
185                Ok(s) => match s.as_str() {
186                    "y" => {
187                        going_to_handle_crumbs_indexes.insert(ind);
188                    }
189                    "n" => {}
190                    "s" => {
191                        continue;
192                    }
193                    _ => {
194                        println!("I don't understand, please give y/n/s");
195                    }
196                },
197                Err(e) => return Err(e.to_string()),
198            }
199            break;
200        }
201    }
202    Ok(going_to_handle_crumbs_indexes)
203}