1use std::path::PathBuf;
2
3use clap::{Parser, Subcommand, ValueEnum};
4
5#[derive(Debug, Clone, Copy, ValueEnum)]
6pub enum FormatArg {
7 Org,
8 Latex,
9 Markdown,
10 Plaintext,
11}
12
13#[derive(Debug, Clone, Copy, ValueEnum)]
14pub enum OutputFormat {
15 Text,
16 Json,
17 Sarif,
18}
19
20#[derive(Debug, Parser)]
21#[command(name = "snapper", version, about = "Semantic line break formatter")]
22pub struct Cli {
23 #[command(subcommand)]
24 pub command: Option<Commands>,
25
26 #[arg()]
28 pub files: Vec<PathBuf>,
29
30 #[arg(short, long)]
32 pub format: Option<FormatArg>,
33
34 #[arg(long)]
36 pub stdin_filepath: Option<PathBuf>,
37
38 #[arg(short, long)]
40 pub output: Option<PathBuf>,
41
42 #[arg(short, long)]
44 pub in_place: bool,
45
46 #[arg(short = 'w', long, default_value_t = 0)]
48 pub max_width: usize,
49
50 #[arg(long)]
52 pub neural: bool,
53
54 #[arg(long)]
56 pub check: bool,
57
58 #[arg(long)]
60 pub diff: bool,
61
62 #[arg(long)]
64 pub config: Option<PathBuf>,
65
66 #[arg(long)]
68 pub range: Option<String>,
69
70 #[arg(long, default_value = "text")]
72 pub output_format: OutputFormat,
73}
74
75#[derive(Debug, Subcommand)]
76pub enum Commands {
77 Init {
79 #[arg(long)]
81 dry_run: bool,
82 },
83}
84
85pub fn parse_range(s: &str) -> Option<(usize, usize)> {
87 let parts: Vec<&str> = s.split(':').collect();
88 if parts.len() != 2 {
89 return None;
90 }
91 let start = parts[0].parse::<usize>().ok()?;
92 let end = parts[1].parse::<usize>().ok()?;
93 if start == 0 || end == 0 || start > end {
94 return None;
95 }
96 Some((start, end))
97}