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}