Skip to main content

to/
error.rs

1use std::fmt::{self, Display, Formatter};
2use std::io;
3use std::path::PathBuf;
4
5pub type Result<T> = std::result::Result<T, AppError>;
6
7#[derive(Debug)]
8pub enum AppError {
9    Io(io::Error),
10    InvalidArgs(String),
11    TodoNotFound(PathBuf),
12    AlreadyInitialized(PathBuf),
13    InvalidTaskIndex { index: usize, len: usize },
14    MalformedTodoLine { line: usize, content: String },
15    NotGitRepository(PathBuf),
16    GitCommandFailed(String),
17    CommandFailed(String),
18    EmptyTask,
19}
20
21impl Display for AppError {
22    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
23        match self {
24            Self::Io(err) => write!(f, "{err}"),
25            Self::InvalidArgs(message) => write!(f, "{message}"),
26            Self::TodoNotFound(path) => write!(
27                f,
28                "no `.todo` file found from {} upward; run `to init` in your project root",
29                path.display()
30            ),
31            Self::AlreadyInitialized(path) => {
32                write!(f, "a `.todo` file already exists at {}", path.display())
33            }
34            Self::InvalidTaskIndex { index, len } => {
35                write!(f, "task {index} is out of range; expected a number between 1 and {len}")
36            }
37            Self::MalformedTodoLine { line, content } => write!(
38                f,
39                "invalid `.todo` format on line {line}: expected `[ ] task` or `[x] task`, got `{content}`"
40            ),
41            Self::NotGitRepository(path) => write!(
42                f,
43                "{} is not inside a git repository; `to scan` only works on git-tracked files",
44                path.display()
45            ),
46            Self::GitCommandFailed(message) => write!(f, "{message}"),
47            Self::CommandFailed(message) => write!(f, "{message}"),
48            Self::EmptyTask => write!(f, "task text cannot be empty"),
49        }
50    }
51}
52
53impl std::error::Error for AppError {}
54
55impl From<io::Error> for AppError {
56    fn from(value: io::Error) -> Self {
57        Self::Io(value)
58    }
59}