1use clap::Parser;
2
3#[derive(Parser, Debug, Clone)]
5#[clap(author, version, about)]
6pub struct Args {
7 #[clap(short = 'd', long, default_value = ".")]
9 pub input: String,
10
11 #[clap(short, long, default_value = "output.md")]
13 pub output: String,
14
15 #[clap(short = 'f', long, value_delimiter = ',')]
17 pub filter: Vec<String>,
18
19 #[clap(short = 'i', long)]
21 pub ignore: Vec<String>,
22
23 #[clap(long)]
25 pub preview: bool,
26
27 #[clap(long)]
29 pub token_count: bool,
30
31 #[clap(long)]
33 pub line_numbers: bool,
34
35 #[clap(short = 'y', long)]
37 pub yes: bool,
38
39 #[clap(long, default_value_t = false)]
41 pub diff_only: bool,
42
43 #[clap(long)]
45 pub clear_cache: bool,
46
47 #[clap(long)]
49 pub init: bool,
50}
51
52#[cfg(test)]
53mod tests {
54 use super::Args;
55 use clap::Parser;
56
57 #[test]
58 fn parses_with_no_args() {
59 let res = Args::try_parse_from(["context-builder"]);
60 assert!(res.is_ok(), "Expected success when no args are provided");
61 }
62
63 #[test]
64 fn parses_all_flags_and_options() {
65 let args = Args::try_parse_from([
66 "context-builder",
67 "--input",
68 "some/dir",
69 "--output",
70 "ctx.md",
71 "--filter",
72 "rs",
73 "--filter",
74 "toml",
75 "--ignore",
76 "target",
77 "--ignore",
78 "node_modules",
79 "--preview",
80 "--token-count",
81 "--line-numbers",
82 "--diff-only",
83 "--clear-cache",
84 ])
85 .expect("should parse");
86
87 assert_eq!(args.input, "some/dir");
88 assert_eq!(args.output, "ctx.md");
89 assert_eq!(args.filter, vec!["rs".to_string(), "toml".to_string()]);
90 assert_eq!(
91 args.ignore,
92 vec!["target".to_string(), "node_modules".to_string()]
93 );
94 assert!(args.preview);
95 assert!(args.token_count);
96 assert!(args.line_numbers);
97 assert!(args.diff_only);
98 assert!(args.clear_cache);
99 }
100
101 #[test]
102 fn short_flags_parse_correctly() {
103 let args = Args::try_parse_from([
104 "context-builder",
105 "-d",
106 ".",
107 "-o",
108 "out.md",
109 "-f",
110 "md",
111 "-f",
112 "rs",
113 "-i",
114 "target",
115 "-i",
116 ".git",
117 ])
118 .expect("should parse");
119
120 assert_eq!(args.input, ".");
121 assert_eq!(args.output, "out.md");
122 assert_eq!(args.filter, vec!["md".to_string(), "rs".to_string()]);
123 assert_eq!(args.ignore, vec!["target".to_string(), ".git".to_string()]);
124 assert!(!args.preview);
125 assert!(!args.line_numbers);
126 assert!(!args.clear_cache);
127 }
128
129 #[test]
130 fn defaults_for_options_when_not_provided() {
131 let args = Args::try_parse_from(["context-builder", "-d", "proj"]).expect("should parse");
132
133 assert_eq!(args.input, "proj");
134 assert_eq!(args.output, "output.md");
135 assert!(args.filter.is_empty());
136 assert!(args.ignore.is_empty());
137 assert!(!args.preview);
138 assert!(!args.line_numbers);
139 assert!(!args.diff_only);
140 assert!(!args.clear_cache);
141 }
142
143 #[test]
144 fn parses_diff_only_flag() {
145 let args = Args::try_parse_from(["context-builder", "--diff-only"])
146 .expect("should parse diff-only flag");
147 assert!(args.diff_only);
148 assert!(!args.clear_cache);
149 }
150
151 #[test]
152 fn parses_clear_cache_flag() {
153 let args = Args::try_parse_from(["context-builder", "--clear-cache"])
154 .expect("should parse clear-cache flag");
155 assert!(args.clear_cache);
156 assert!(!args.diff_only);
157 }
158}