rustask/
commands.rs

1use std::path::Path;
2
3pub mod error;
4pub mod project;
5mod storage;
6pub mod task;
7
8use project::Project;
9use task::Task;
10
11fn list_filter<F>(path: &Path, project: Option<String>, op: F) -> Result<(), error::RustaskError>
12where
13    F: Fn(&usize, &Task) -> bool,
14{
15    let projects = storage::load_tasks(&path)?;
16    match project {
17        None => {
18            let projs = storage::load_tasks(&path)?;
19            for (i, proj) in projs.iter().enumerate() {
20                println!("{}", proj);
21                proj.tasks()
22                    .iter()
23                    .enumerate()
24                    .filter(|(i, t)| op(i, *t))
25                    .for_each(|(idx, t)| println!("[{}]: {}", idx, t));
26                if i != projs.len() - 1 {
27                    println!("");
28                }
29            }
30            Ok(())
31        }
32        Some(name) => {
33            if let Some(idx) = projects.iter().position(|p| p.name == name) {
34                println!("{}", projects[idx]);
35                projects[idx]
36                    .tasks()
37                    .iter()
38                    .enumerate()
39                    .filter(|(i, t)| op(i, *t))
40                    .for_each(|(idx, t)| println!("[{}]: {}", idx, t));
41                Ok(())
42            } else {
43                Err(error::RustaskError::ProjectNotFound(name))
44            }
45        }
46    }
47}
48
49/// List the tasks in the path given
50pub fn list_all(path: &Path, project: Option<String>) -> Result<(), error::RustaskError> {
51    list_filter(path, project, |_a, _b| true)
52}
53
54/// List the tasks in the path given (depends on priority)
55pub fn list(path: &Path, project: Option<String>) -> Result<(), error::RustaskError> {
56    list_filter(path, project, |_, t| t.choose())
57}
58
59/// Renames a project if it exists and if the other name is not taken
60pub fn rename(path: &Path, project: String, name: String) -> Result<(), error::RustaskError> {
61    let mut projs = storage::load_tasks(&path)?;
62    if let Some(idx) = projs.iter().position(|p| p.name == project) {
63        if projs.iter().any(|p| p.name == name) {
64            return Err(error::RustaskError::ProjectNameTaken(name));
65        }
66        projs[idx].rename(name);
67    } else {
68        return Err(error::RustaskError::ProjectNotFound(project));
69    }
70    storage::store_tasks(&path, &projs)
71}
72
73/// Add a new task
74pub fn add_task(path: &Path, task: Task, name: String) -> Result<(), error::RustaskError> {
75    let mut projs = storage::load_tasks(&path)?;
76    if let Some(idx) = projs.iter().position(|p| p.name == name) {
77        projs[idx].push(task);
78    } else {
79        let mut p = Project::new(name);
80        p.push(task);
81        projs.push(p);
82        projs.sort();
83    }
84
85    storage::store_tasks(&path, &projs)
86}
87
88/// Remove a task
89pub fn remove_task(path: &Path, id: usize, name: String) -> Result<Task, error::RustaskError> {
90    let mut projs = storage::load_tasks(&path)?;
91    let idx_res = projs.iter().position(|p| p.name == name);
92    if idx_res.is_none() {
93        return Err(error::RustaskError::ProjectNotFound(name));
94    }
95
96    let idx = idx_res.unwrap();
97
98    let task = projs[idx].remove(id)?;
99    if projs[idx].len() == 0 {
100        projs.remove(idx);
101    }
102    storage::store_tasks(&path, &projs)?;
103    Ok(task)
104}
105
106pub fn move_task(
107    path: &Path,
108    old_project: String,
109    id: usize,
110    new_project: String,
111) -> Result<(), error::RustaskError> {
112    let task = remove_task(path, id, old_project)?;
113    add_task(path, task, new_project)
114}
115
116/// Edit a task
117pub fn edit_task(
118    path: &Path,
119    id: usize,
120    name: String,
121    description: Option<String>,
122    priority: Option<task::Priority>,
123    deadline: Option<task::Deadline>,
124) -> Result<(), error::RustaskError> {
125    let mut projs = storage::load_tasks(&path)?;
126    let idx_res = projs.iter().position(|p| p.name == name);
127    if idx_res.is_none() {
128        return Err(error::RustaskError::ProjectNotFound(name));
129    }
130
131    let idx = idx_res.unwrap();
132    projs[idx].edit(id, |mut task| {
133        if let Some(d) = description {
134            task.description = d;
135        }
136        if let Some(p) = priority {
137            task.priority = Some(p);
138        }
139        if let Some(d) = deadline {
140            task.deadline = Some(d);
141        }
142    })?;
143    storage::store_tasks(&path, &projs)?;
144    Ok(())
145}