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 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" => (), "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" => (), "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 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}