1use crate::{text_from_editor, Args, Entry};
2use clap::{Arg, ArgMatches, Command};
3
4pub fn get_args() -> ArgMatches {
5 Command::new("Notebook")
6 .about("CLI utility for plaintext notetaking.")
7 .subcommand_required(true)
8 .arg_required_else_help(true)
9 .subcommand(
10 Command::new("new")
11 .short_flag('n')
12 .long_flag("new")
13 .about("Create a new note")
14 .arg(Arg::new("entry")),
15 )
16 .arg(
17 Arg::new("notebook_name")
18 .short('j')
19 .long("notebook")
20 .default_value("default")
21 .help("Specify a notebook name"),
22 )
23 .subcommand(
24 Command::new("list")
25 .short_flag('l')
26 .long_flag("list")
27 .about("List entries")
28 .arg(Arg::new("list").default_value("5")),
29 )
30 .arg(
31 Arg::new("verbose")
32 .short('v')
33 .long("verbose")
34 .help("Quantity of information")
35 .action(clap::ArgAction::Count),
36 )
37 .subcommand(
38 Command::new("edit")
39 .short_flag('e')
40 .long_flag("edit")
41 .about("Edit specific entry")
42 .arg(Arg::new("edit")),
43 )
44 .subcommand(
45 Command::new("read")
46 .short_flag('r')
47 .long_flag("read")
48 .about("Display specific entry")
49 .arg(Arg::new("read")),
50 )
51 .subcommand(
52 Command::new("delete")
53 .short_flag('X')
54 .long_flag("delete")
55 .about("Delete specific entry")
56 .arg(Arg::new("delete")),
57 )
58 .subcommand(
59 Command::new("date search")
60 .short_flag('d')
61 .long_flag("date-search")
62 .about("Search for entries around a date")
63 .arg(Arg::new("datesearch")),
64 )
65 .subcommand(
66 Command::new("search")
67 .short_flag('s')
68 .long_flag("search")
69 .about("Query to search, enclosed in quotations")
70 .arg(Arg::new("search"))
71 .subcommand(
72 Command::new("date")
73 .short_flag('d')
74 .long_flag("date")
75 .about("Filter results by date range")
76 .arg(Arg::new("entry")),
77 ),
78 )
79 .arg(
80 Arg::new("config")
81 .short('c')
82 .long("config")
83 .help("Path of config file to read"),
84 )
85 .get_matches()
86}
87
88pub fn parse_args(matches: ArgMatches, dt_format: &str) -> Args {
89 let verbose = matches.get_count("verbose");
90
91 match matches.subcommand() {
92 Some(("new", input)) => {
93 let text: String = match input.get_many::<String>("entry") {
94 Some(t) => t.fold(String::new(), |mut a, b| {
95 a.reserve(b.len() + 1);
96 a.push_str(b);
97 a.push(' ');
98 a
99 }),
100
101 None => text_from_editor(None).unwrap(),
102 };
103 let e = Entry::new(text, dt_format);
104 Args::New(e)
105 }
106
107 Some(("list", input)) => {
108 let n: usize = input.get_one::<String>("list").unwrap().parse().unwrap();
109 Args::List(n, verbose)
110 }
111
112 Some(("read", input)) => {
113 let n: usize = input.get_one::<String>("read").unwrap().parse().unwrap();
114 Args::Read(n)
115 }
116
117 Some(("edit", input)) => {
118 let n: usize = input.get_one::<String>("edit").unwrap().parse().unwrap();
119 Args::Edit(n)
120 }
121
122 Some(("delete", input)) => {
123 let n: usize = input.get_one::<String>("delete").unwrap().parse().unwrap();
124 Args::Delete(n, true)
125 }
126
127 Some(("search", input)) => {
128 let mut q = String::new();
129 let search_command = input.subcommand().unwrap_or(("search", input));
130 match search_command {
131 ("date", _sub_matches) => Args::DateFilter(q),
132 ("search", _sub_matches) => {
133 q = input.get_one::<String>("search").unwrap().into();
134 Args::Search(q)
135 }
136 (name, _) => {
137 unreachable!("Unsupported subcommand `{name}`")
138 }
139 }
140 }
141
142 Some(("date search", input)) => {
143 let date = input.get_one::<String>("search").unwrap().into();
144 Args::DateSearch(date)
145 }
146
147 _ => unreachable!(),
148 }
149}