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
48#[cfg(test)]
49mod tests {
50 use super::Args;
51 use clap::Parser;
52
53 #[test]
54 fn parses_with_no_args() {
55 let res = Args::try_parse_from(["context-builder"]);
56 assert!(res.is_ok(), "Expected success when no args are provided");
57 }
58
59 #[test]
60 fn parses_all_flags_and_options() {
61 let args = Args::try_parse_from([
62 "context-builder",
63 "--input",
64 "some/dir",
65 "--output",
66 "ctx.md",
67 "--filter",
68 "rs",
69 "--filter",
70 "toml",
71 "--ignore",
72 "target",
73 "--ignore",
74 "node_modules",
75 "--preview",
76 "--token-count",
77 "--line-numbers",
78 "--diff-only",
79 "--clear-cache",
80 ])
81 .expect("should parse");
82
83 assert_eq!(args.input, "some/dir");
84 assert_eq!(args.output, "ctx.md");
85 assert_eq!(args.filter, vec!["rs".to_string(), "toml".to_string()]);
86 assert_eq!(
87 args.ignore,
88 vec!["target".to_string(), "node_modules".to_string()]
89 );
90 assert!(args.preview);
91 assert!(args.token_count);
92 assert!(args.line_numbers);
93 assert!(args.diff_only);
94 assert!(args.clear_cache);
95 }
96
97 #[test]
98 fn short_flags_parse_correctly() {
99 let args = Args::try_parse_from([
100 "context-builder",
101 "-d",
102 ".",
103 "-o",
104 "out.md",
105 "-f",
106 "md",
107 "-f",
108 "rs",
109 "-i",
110 "target",
111 "-i",
112 ".git",
113 ])
114 .expect("should parse");
115
116 assert_eq!(args.input, ".");
117 assert_eq!(args.output, "out.md");
118 assert_eq!(args.filter, vec!["md".to_string(), "rs".to_string()]);
119 assert_eq!(args.ignore, vec!["target".to_string(), ".git".to_string()]);
120 assert!(!args.preview);
121 assert!(!args.line_numbers);
122 assert!(!args.clear_cache);
123 }
124
125 #[test]
126 fn defaults_for_options_when_not_provided() {
127 let args = Args::try_parse_from(["context-builder", "-d", "proj"]).expect("should parse");
128
129 assert_eq!(args.input, "proj");
130 assert_eq!(args.output, "output.md");
131 assert!(args.filter.is_empty());
132 assert!(args.ignore.is_empty());
133 assert!(!args.preview);
134 assert!(!args.line_numbers);
135 assert!(!args.diff_only);
136 assert!(!args.clear_cache);
137 }
138
139 #[test]
140 fn parses_diff_only_flag() {
141 let args = Args::try_parse_from(["context-builder", "--diff-only"])
142 .expect("should parse diff-only flag");
143 assert!(args.diff_only);
144 assert!(!args.clear_cache);
145 }
146
147 #[test]
148 fn parses_clear_cache_flag() {
149 let args = Args::try_parse_from(["context-builder", "--clear-cache"])
150 .expect("should parse clear-cache flag");
151 assert!(args.clear_cache);
152 assert!(!args.diff_only);
153 }
154}