tasker_cli/execution/
mod.rs

1mod helpers;
2
3use crate::{
4    cli::{
5        AddTasks, Cli, Command, DeleteTasks, EditTask, ListTasks, ToggleTasks,
6    },
7    config::{Configuration, Language},
8};
9use anyhow::bail;
10use helpers::{get_next_index, list_to_dos};
11use lib_tasker::{
12    io::get_project_directories,
13    todos::{State, Task, ToDo},
14};
15use owo_colors::OwoColorize;
16
17/// Executes the application.
18///
19/// # Errors
20///
21/// Returns an error if the execution of the application failed at any point.
22pub fn execute_application(cli: Cli) -> anyhow::Result<()> {
23    let configuration = if let Some(path) = cli.config_file {
24        Configuration::from_given_file(&path)?
25    } else {
26        let to_do_path = if let Some(path) = cli.todo_file {
27            path
28        } else {
29            ToDo::get_default_to_do_path()?
30        };
31
32        Configuration::new(&to_do_path)?
33    };
34
35    match cli.command {
36        Some(Command::Add(add)) => add_tasks(add, &configuration)?,
37        Some(Command::Clean) => clean_completed_tasks(&configuration)?,
38        Some(Command::Delete(delete)) => delete_tasks(&delete, &configuration)?,
39        Some(Command::Edit(edit)) => edit_task(edit, &configuration)?,
40        Some(Command::List(list)) => list_tasks(list, &configuration)?,
41        Some(Command::Paths) => get_paths()?,
42        Some(Command::Toggle(toggle)) => toggle_tasks(&toggle, &configuration)?,
43        None => {
44            let to_do = ToDo::get_to_do(&configuration.to_do_path)?;
45
46            list_to_dos(to_do, &configuration, None);
47        }
48    }
49
50    Ok(())
51}
52
53fn add_tasks(to_add: AddTasks, config: &Configuration) -> anyhow::Result<()> {
54    let mut to_do = ToDo::get_to_do(&config.to_do_path)?;
55    let mut next_index = get_next_index(&to_do);
56
57    match to_add.project {
58        Some(project) => {
59            to_do
60                .tasks
61                .extend(to_add.descriptions.into_iter().map(|desc| {
62                    let index = next_index;
63                    next_index += 1;
64
65                    Task::create(desc)
66                        .id(index)
67                        .project(project.clone())
68                        .tags(to_add.tag.clone().unwrap_or_default())
69                        .build()
70                }));
71        }
72        None => {
73            to_do
74                .tasks
75                .extend(to_add.descriptions.into_iter().map(|desc| {
76                    let index = next_index;
77                    next_index += 1;
78
79                    Task::create(desc)
80                        .id(index)
81                        .tags(to_add.tag.clone().unwrap_or_default())
82                        .build()
83                }));
84        }
85    }
86
87    match to_do.save(&config.to_do_path) {
88        Ok(()) => match config.language {
89            Language::English => println!("{}", "Added Tasks".green()),
90            Language::Spanish => {
91                println!("{}", "Tareas aƱadidas".green());
92            }
93        },
94        Err(err) => match config.language {
95            Language::English => {
96                bail!("Failed to save Task file: {}", err.red())
97            }
98            Language::Spanish => {
99                bail!("No se pudo guardar archivo de Tareas: {}", err.red())
100            }
101        },
102    }
103
104    Ok(())
105}
106
107fn clean_completed_tasks(config: &Configuration) -> anyhow::Result<()> {
108    let mut to_do = ToDo::get_to_do(&config.to_do_path)?;
109
110    to_do.tasks.retain(|task| task.state != State::Done);
111
112    match to_do.save(&config.to_do_path) {
113        Ok(()) => match config.language {
114            Language::English => {
115                println!("{}", "Cleaned completed tasks".purple());
116            }
117            Language::Spanish => {
118                println!("{}", "Se limpiaron las Tareas completadas".purple());
119            }
120        },
121        Err(err) => match config.language {
122            Language::English => {
123                bail!("Failed to save Task file: {}", err.red())
124            }
125            Language::Spanish => {
126                bail!("No se pudo guardar archivo de Tareas: {}", err.red())
127            }
128        },
129    }
130
131    Ok(())
132}
133
134fn delete_tasks(
135    to_delete: &DeleteTasks,
136    config: &Configuration,
137) -> anyhow::Result<()> {
138    let mut to_do = ToDo::get_to_do(&config.to_do_path)?;
139
140    to_do
141        .tasks
142        .retain(|task| !to_delete.tasks.contains(&task.id));
143
144    match to_do.save(&config.to_do_path) {
145        Ok(()) => match config.language {
146            Language::English => println!("{}", "Deleted Tasks".red()),
147            Language::Spanish => {
148                println!("{}", "Tareas eliminadas".red());
149            }
150        },
151        Err(err) => match config.language {
152            Language::English => {
153                bail!("Failed to save Task file: {}", err.red())
154            }
155            Language::Spanish => {
156                bail!("No se pudo guardar archivo de Tareas: {}", err.red())
157            }
158        },
159    }
160
161    Ok(())
162}
163
164fn edit_task(to_edit: EditTask, config: &Configuration) -> anyhow::Result<()> {
165    let mut to_do = ToDo::get_to_do(&config.to_do_path)?;
166
167    match to_do.tasks.iter_mut().find(|task| task.id == to_edit.task) {
168        Some(task) => {
169            if let Some(description) = to_edit.description {
170                task.description = description;
171            }
172
173            if let Some(project) = to_edit.project {
174                task.project = project;
175            }
176
177            if let Some(state) = to_edit.state {
178                task.state = state.into();
179            }
180
181            if let Some(tags) = to_edit.tags {
182                task.replace_tags(tags);
183            }
184        }
185        None => match config.language {
186            Language::English => bail!("Task doesn't exist".red()),
187            Language::Spanish => bail!("Tarea no existe".red()),
188        },
189    }
190
191    match to_do.save(&config.to_do_path) {
192        Ok(()) => match config.language {
193            Language::English => println!("{}", "Edited Task".blue()),
194            Language::Spanish => println!("{}", "Tarea editada".blue()),
195        },
196        Err(err) => match config.language {
197            Language::English => {
198                bail!("Failed to save Task file: {}", err.red())
199            }
200            Language::Spanish => {
201                bail!("No se pudo guardar archivo de Tareas: {}", err.red())
202            }
203        },
204    }
205
206    Ok(())
207}
208
209fn list_tasks(
210    to_list: ListTasks,
211    config: &Configuration,
212) -> anyhow::Result<()> {
213    let to_do = ToDo::get_to_do(&config.to_do_path)?;
214    list_to_dos(to_do, config, Some(to_list));
215
216    Ok(())
217}
218
219fn get_paths() -> anyhow::Result<()> {
220    let paths = get_project_directories()?;
221
222    println!("Config path: {}", paths.config_dir().display());
223    println!("Data path: {}", paths.data_dir().display());
224
225    Ok(())
226}
227
228fn toggle_tasks(
229    to_toggle: &ToggleTasks,
230    config: &Configuration,
231) -> anyhow::Result<()> {
232    let mut to_do = ToDo::get_to_do(&config.to_do_path)?;
233
234    to_do
235        .tasks
236        .iter_mut()
237        .filter(|task| to_toggle.tasks.contains(&task.id))
238        .for_each(|task| task.change_state(to_toggle.state.into()));
239
240    match to_do.save(&config.to_do_path) {
241        Ok(()) => match config.language {
242            Language::English => {
243                println!("{}", "State changed".yellow());
244            }
245            Language::Spanish => {
246                println!("{}", "Estado cambiado".yellow());
247            }
248        },
249        Err(err) => match config.language {
250            Language::English => {
251                bail!("Failed to save Task file: {}", err.red())
252            }
253            Language::Spanish => {
254                bail!("No se pudo guardar archivo de Tareas: {}", err.red())
255            }
256        },
257    }
258
259    Ok(())
260}