1use clap::Parser;
6
7#[derive(Parser, Debug)]
8#[command(
9 name = "rusty-vipe",
10 version,
11 about = "Pop $EDITOR mid-pipe; edit the buffered bytes; resume the pipeline.",
12 long_about = "A Rust port of moreutils `vipe`. Buffers stdin to a tempfile, \
13 spawns $EDITOR on it with cross-platform TTY reattachment, then \
14 writes the post-edit bytes back to the original stdout sink."
15)]
16pub struct Cli {
17 #[arg(long = "suffix", value_parser = parse_suffix_arg)]
20 pub suffix: Option<String>,
21
22 #[arg(long = "editor")]
25 pub editor: Option<String>,
26
27 #[arg(long, conflicts_with = "no_strict")]
29 pub strict: bool,
30
31 #[arg(long = "no-strict")]
33 pub no_strict: bool,
34
35 #[arg(trailing_var_arg = true)]
38 pub editor_extras: Vec<String>,
39
40 #[command(subcommand)]
42 pub command: Option<Subcommand>,
43}
44
45#[derive(clap::Subcommand, Debug)]
46pub enum Subcommand {
47 Completions { shell: clap_complete::Shell },
49}
50
51fn parse_suffix_arg(value: &str) -> Result<String, String> {
54 crate::validate_suffix(value).map_err(|e| e.to_string())?;
55 Ok(value.to_string())
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61 use clap::CommandFactory;
62
63 #[test]
64 fn cli_command_factory_compiles() {
65 let cmd = Cli::command();
66 assert_eq!(cmd.get_name(), "rusty-vipe");
67 }
68
69 #[test]
70 fn parse_no_args() {
71 let cli = Cli::try_parse_from(["rusty-vipe"]).unwrap();
72 assert!(cli.suffix.is_none());
73 assert!(cli.editor.is_none());
74 assert!(!cli.strict);
75 assert!(!cli.no_strict);
76 }
77
78 #[test]
79 fn parse_suffix() {
80 let cli = Cli::try_parse_from(["rusty-vipe", "--suffix=.json"]).unwrap();
81 assert_eq!(cli.suffix.as_deref(), Some(".json"));
82 }
83
84 #[test]
85 fn parse_editor_override() {
86 let cli = Cli::try_parse_from(["rusty-vipe", "--editor=code --wait"]).unwrap();
87 assert_eq!(cli.editor.as_deref(), Some("code --wait"));
88 }
89
90 #[test]
91 fn parse_strict_conflicts_with_no_strict() {
92 let result = Cli::try_parse_from(["rusty-vipe", "--strict", "--no-strict"]);
93 assert!(result.is_err());
94 }
95}