typst_count/cli.rs
1//! Command-line interface definitions for typst-count.
2//!
3//! This module defines the CLI structure using `clap`, including all command-line
4//! arguments, options, and their associated enums for output formats and counting modes.
5
6use clap::{Parser, ValueEnum};
7use std::path::PathBuf;
8
9/// Command-line arguments for the typst-count tool.
10///
11/// This structure defines all available options for counting words and characters
12/// in Typst documents, including input files, output formats, counting modes,
13/// and various filtering and limiting options.
14#[derive(Parser)]
15#[command(name = "typst-count")]
16#[command(version, about = "Count words and characters in Typst documents")]
17#[command(long_about = "Count words and characters in Typst documents.\n\n\
18 Counts are based on the compiled document, meaning only rendered \
19 text is counted. Code, markup, headers, and footers are excluded.")]
20pub struct Cli {
21 /// Path(s) to Typst document(s) to count.
22 ///
23 /// Multiple files can be specified to get counts for each file plus totals.
24 /// Path(s) to Typst document(s)
25 #[arg(required = true, value_name = "FILE")]
26 pub input: Vec<PathBuf>,
27
28 /// Output format for results.
29 ///
30 /// Available formats:
31 /// - `human`: Human-readable table format (default)
32 /// - `json`: JSON format for machine processing
33 /// - `csv`: CSV format for spreadsheet import
34 #[arg(short = 'f', long, value_enum, default_value_t = OutputFormat::Human)]
35 pub format: OutputFormat,
36
37 /// What to count in the documents.
38 ///
39 /// - `both`: Count both words and characters (default)
40 /// - `words`: Count only words
41 /// - `characters`: Count only characters
42 #[arg(short = 'm', long = "mode", value_enum, default_value_t = CountMode::Both)]
43 pub mode: CountMode,
44
45 /// Write output to a file instead of stdout.
46 ///
47 /// If not specified, output is written to stdout. The file format is
48 /// determined by the `--format` option.
49 #[arg(short = 'o', long = "output", value_name = "FILE")]
50 pub output: Option<PathBuf>,
51
52 /// Display mode when processing multiple files.
53 ///
54 /// - `auto`: Detailed for multiple files, simple for single file (default)
55 /// - `total`: Show only totals, no per-file breakdown
56 /// - `quiet`: Suppress labels, output only numbers
57 /// - `detailed`: Always show per-file breakdown
58 #[arg(short = 'd', long = "display", value_enum, default_value_t = DisplayMode::Auto)]
59 pub display: DisplayMode,
60
61 /// Exclude content from imported/included files.
62 ///
63 /// By default, text from all imported and included files is counted.
64 /// Use this flag to count only the main file(s) specified on the command line.
65 #[arg(short = 'e', long = "exclude-imports")]
66 pub exclude_imports: bool,
67
68 /// Exit with error if word count exceeds this limit.
69 ///
70 /// Useful for CI/CD pipelines to enforce maximum document length.
71 /// Exit code will be 1 if the limit is exceeded.
72 #[arg(long, value_name = "N")]
73 pub max_words: Option<usize>,
74
75 /// Exit with error if word count is below this limit.
76 ///
77 /// Useful for CI/CD pipelines to enforce minimum document length.
78 /// Exit code will be 1 if the count is below the limit.
79 #[arg(long, value_name = "N")]
80 pub min_words: Option<usize>,
81
82 /// Exit with error if character count exceeds this limit.
83 ///
84 /// Useful for CI/CD pipelines to enforce maximum document size.
85 /// Exit code will be 1 if the limit is exceeded.
86 #[arg(long, value_name = "N")]
87 pub max_characters: Option<usize>,
88
89 /// Exit with error if character count is below this limit.
90 ///
91 /// Useful for CI/CD pipelines to enforce minimum document size.
92 /// Exit code will be 1 if the count is below the limit.
93 #[arg(long, value_name = "N")]
94 pub min_characters: Option<usize>,
95}
96
97/// Output format for displaying count results.
98///
99/// Determines how the word and character counts are formatted and presented.
100#[derive(Clone, Copy, ValueEnum, Debug)]
101pub enum OutputFormat {
102 /// Human-readable table format (default).
103 ///
104 /// Displays results in an easy-to-read format with labels and formatting.
105 Human,
106 /// JSON output for machine processing.
107 ///
108 /// Outputs results as JSON with file paths, counts, and totals.
109 /// Suitable for parsing by scripts and other tools.
110 Json,
111 /// CSV output for spreadsheet import.
112 ///
113 /// Outputs results in comma-separated values format, suitable for
114 /// importing into spreadsheet applications or data analysis tools.
115 Csv,
116}
117
118/// What to count in the document.
119///
120/// Determines whether to count words, characters, or both.
121#[derive(Clone, Copy, ValueEnum, PartialEq, Eq, Debug)]
122pub enum CountMode {
123 /// Count both words and characters (default).
124 Both,
125 /// Count only words.
126 ///
127 /// Words are counted by splitting on whitespace.
128 Words,
129 /// Count only characters.
130 ///
131 /// Counts all Unicode scalar values including spaces and punctuation.
132 Characters,
133}
134
135/// Display mode for formatting output when processing multiple files.
136///
137/// Controls how detailed the output should be and how results are presented.
138#[derive(Clone, Copy, ValueEnum, PartialEq, Eq, Debug)]
139pub enum DisplayMode {
140 /// Automatic mode (default).
141 ///
142 /// Shows detailed breakdown for multiple files, simple output for single file.
143 Auto,
144 /// Show only totals without per-file breakdown.
145 ///
146 /// Useful when you only care about aggregate counts across all files.
147 Total,
148 /// Suppress all labels and output only numbers.
149 ///
150 /// Outputs raw numbers only, suitable for piping to other commands.
151 Quiet,
152 /// Always show detailed per-file breakdown.
153 ///
154 /// Shows counts for each file individually even for single files.
155 Detailed,
156}