1use anyhow::{Context, Result};
2use clap::{Parser, Subcommand};
3use std::fs::File;
4use std::fs::OpenOptions;
5use std::io::{BufRead, BufReader};
6
7#[derive(Debug, Parser)] #[command(name = "todo-cli-app")]
10#[command(about = "Yet another todo CLI app written in Rust", long_about = None)]
11pub struct Cli {
12 #[arg(short, long)]
14 pub file: Option<String>,
15 #[command(subcommand)]
16 pub command: Commands,
17}
18
19#[derive(Debug, Subcommand)]
20pub enum Commands {
21 Init { path: Option<String> },
23
24 Add { task: String },
26
27 RM { number: usize },
29
30 List {},
32
33 Done { number: usize },
35
36 Clear {},
38
39 SORT {},
41
42 EDIT { number: usize },
44
45 SYNC {},
47
48 CLEAN {},
50}
51
52pub fn check_file(file_path: &str) -> Result<File> {
53 let todofile = OpenOptions::new()
54 .create(true)
55 .append(true)
56 .open(file_path)
57 .with_context(|| format!("Failed to open or create file: {}", file_path))?;
58
59 Ok(todofile)
60}
61
62pub fn read_line(path: &str, target_string: &str) -> Option<u32> {
63 let file = BufReader::new(File::open(path).expect("Unable to open file"));
64 let mut current_line_number = 1;
65
66 for line in file.lines() {
67 current_line_number += 1;
68
69 if let Ok(content) = line {
70 if content.contains(target_string) {
71 return Some(current_line_number);
72 }
73 }
74 }
75 if current_line_number == 0 {
76 return Some(0);
77 } else {
78 return Some(current_line_number);
79 }
80}