1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum OutputPolicy {
16 Passthrough,
20
21 Verbatim,
25
26 Compressible,
30}
31
32impl OutputPolicy {
33 pub fn is_protected(&self) -> bool {
36 matches!(self, Self::Passthrough | Self::Verbatim)
37 }
38}
39
40pub fn classify(command: &str, user_excluded: &[String]) -> OutputPolicy {
47 if is_passthrough(command, user_excluded) {
48 return OutputPolicy::Passthrough;
49 }
50 if super::compress::is_verbatim_output(command) {
51 return OutputPolicy::Verbatim;
52 }
53 OutputPolicy::Compressible
54}
55
56fn is_passthrough(command: &str, user_excluded: &[String]) -> bool {
57 super::compress::is_excluded_command(command, user_excluded)
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn gh_auth_is_passthrough() {
66 assert_eq!(classify("gh auth login", &[]), OutputPolicy::Passthrough);
67 }
68
69 #[test]
70 fn gh_api_is_verbatim() {
71 assert_eq!(
73 classify("gh api repos/owner/repo/issues", &[]),
74 OutputPolicy::Verbatim
75 );
76 }
77
78 #[test]
79 fn user_excluded_is_passthrough() {
80 let excl = vec!["mycommand".to_string()];
81 assert_eq!(
82 classify("mycommand --flag", &excl),
83 OutputPolicy::Passthrough
84 );
85 }
86
87 #[test]
88 fn curl_is_verbatim() {
89 assert_eq!(
90 classify("curl https://api.example.com", &[]),
91 OutputPolicy::Verbatim
92 );
93 }
94
95 #[test]
96 fn cat_is_verbatim() {
97 assert_eq!(classify("cat package.json", &[]), OutputPolicy::Verbatim);
98 }
99
100 #[test]
101 fn cargo_build_is_compressible() {
102 assert_eq!(classify("cargo build", &[]), OutputPolicy::Compressible);
103 }
104
105 #[test]
106 fn npm_test_is_compressible() {
107 assert_eq!(classify("npm test", &[]), OutputPolicy::Compressible);
108 }
109
110 #[test]
111 fn dev_server_is_passthrough() {
112 assert_eq!(classify("npm run dev", &[]), OutputPolicy::Passthrough);
113 assert_eq!(classify("cargo watch", &[]), OutputPolicy::Passthrough);
114 assert_eq!(classify("cargo run", &[]), OutputPolicy::Passthrough);
115 }
116
117 #[test]
118 fn git_diff_is_verbatim() {
119 let policy = classify("git diff", &[]);
124 assert_eq!(policy, OutputPolicy::Compressible);
129 }
130
131 #[test]
132 fn auth_commands_are_passthrough() {
133 assert_eq!(classify("az login", &[]), OutputPolicy::Passthrough);
134 assert_eq!(
135 classify("gcloud auth login", &[]),
136 OutputPolicy::Passthrough
137 );
138 assert_eq!(classify("firebase login", &[]), OutputPolicy::Passthrough);
139 }
140
141 #[test]
142 fn jq_is_verbatim() {
143 assert_eq!(
144 classify("jq '.items' data.json", &[]),
145 OutputPolicy::Verbatim
146 );
147 }
148
149 #[test]
150 fn unknown_command_is_compressible() {
151 assert_eq!(
152 classify("some-random-tool --flag", &[]),
153 OutputPolicy::Compressible
154 );
155 }
156
157 #[test]
158 fn piped_jq_is_verbatim() {
159 assert_eq!(
160 classify("kubectl get pods -o json | jq '.items[]'", &[]),
161 OutputPolicy::Verbatim
162 );
163 }
164
165 #[test]
166 fn policy_is_protected() {
167 assert!(OutputPolicy::Passthrough.is_protected());
168 assert!(OutputPolicy::Verbatim.is_protected());
169 assert!(!OutputPolicy::Compressible.is_protected());
170 }
171
172 #[test]
175 fn issue_198_gh_api_jq() {
176 assert_eq!(
178 classify("gh api repos/yvgude/lean-ctx/issues/198 --jq '.body'", &[]),
179 OutputPolicy::Verbatim
180 );
181 }
182
183 #[test]
184 fn issue_159_cat_pubspec() {
185 assert_eq!(classify("cat pubspec.yaml", &[]), OutputPolicy::Verbatim);
186 }
187
188 #[test]
189 fn issue_114_git_stash() {
190 let p = classify("git stash show", &[]);
195 assert_eq!(p, OutputPolicy::Compressible);
196 }
197
198 #[test]
199 fn issue_194_git_diff_raw() {
200 let p = classify("git diff --cached", &[]);
202 assert_eq!(p, OutputPolicy::Compressible);
203 }
204
205 #[test]
206 fn npm_install_is_compressible() {
207 assert_eq!(
209 classify("npm install -g deepseek-tui", &[]),
210 OutputPolicy::Compressible
211 );
212 }
213
214 #[test]
215 fn pip_install_is_compressible() {
216 assert_eq!(
217 classify("pip install flask", &[]),
218 OutputPolicy::Compressible
219 );
220 }
221
222 #[test]
223 fn kubectl_get_yaml_is_verbatim() {
224 assert_eq!(
225 classify("kubectl get pods -o yaml", &[]),
226 OutputPolicy::Verbatim
227 );
228 }
229
230 #[test]
231 fn docker_inspect_is_verbatim() {
232 assert_eq!(
233 classify("docker inspect my-container", &[]),
234 OutputPolicy::Verbatim
235 );
236 }
237
238 #[test]
239 fn terraform_output_is_verbatim() {
240 assert_eq!(classify("terraform output", &[]), OutputPolicy::Verbatim);
241 }
242
243 #[test]
244 fn heroku_logs_is_verbatim() {
245 assert_eq!(classify("heroku logs --tail", &[]), OutputPolicy::Verbatim);
246 }
247
248 #[test]
249 fn gh_pr_list_is_compressible() {
250 assert_eq!(classify("gh pr list", &[]), OutputPolicy::Compressible);
251 }
252
253 #[test]
254 fn lean_ctx_is_passthrough() {
255 assert_eq!(
256 classify("lean-ctx init powershell", &[]),
257 OutputPolicy::Passthrough
258 );
259 assert_eq!(
260 classify("lean-ctx overview", &[]),
261 OutputPolicy::Passthrough
262 );
263 }
264
265 #[test]
266 fn stripe_list_is_verbatim() {
267 assert_eq!(classify("stripe charges list", &[]), OutputPolicy::Verbatim);
268 }
269
270 #[test]
273 fn git_commit_is_verbatim() {
274 assert_eq!(
275 classify("git commit -m \"feat: add feature\"", &[]),
276 OutputPolicy::Verbatim
277 );
278 }
279
280 #[test]
281 fn git_push_is_verbatim() {
282 assert_eq!(
283 classify("git push origin main", &[]),
284 OutputPolicy::Verbatim
285 );
286 }
287
288 #[test]
289 fn git_pull_is_verbatim() {
290 assert_eq!(classify("git pull --rebase", &[]), OutputPolicy::Verbatim);
291 }
292
293 #[test]
294 fn git_merge_is_verbatim() {
295 assert_eq!(
296 classify("git merge feature-branch", &[]),
297 OutputPolicy::Verbatim
298 );
299 }
300
301 #[test]
302 fn git_rebase_is_verbatim() {
303 assert_eq!(classify("git rebase main", &[]), OutputPolicy::Verbatim);
304 }
305
306 #[test]
307 fn git_cherry_pick_is_verbatim() {
308 assert_eq!(
309 classify("git cherry-pick abc1234", &[]),
310 OutputPolicy::Verbatim
311 );
312 }
313
314 #[test]
315 fn git_tag_is_verbatim() {
316 assert_eq!(classify("git tag v1.0.0", &[]), OutputPolicy::Verbatim);
317 }
318
319 #[test]
320 fn git_status_still_compressible() {
321 assert_eq!(classify("git status", &[]), OutputPolicy::Compressible);
322 }
323
324 #[test]
325 fn git_log_still_compressible() {
326 assert_eq!(
327 classify("git log --oneline", &[]),
328 OutputPolicy::Compressible
329 );
330 }
331}