1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// src/cli.rs
use clap::Parser;
// use std::path::PathBuf; // Not used directly here
/// High-performance Rust utility that concatenates and displays directory contents,
/// respecting .gitignore rules and offering various filtering/formatting options.
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
#[command(propagate_version = true)]
pub struct Cli {
/// Path to the directory/file to process, or a git repository URL to clone.
#[arg(default_value = ".")]
pub input_path: String,
// --- Git Options ---
/// For git URL inputs, clone a specific branch instead of the default.
#[arg(long, value_name = "BRANCH")]
pub git_branch: Option<String>,
/// For git URL inputs, perform a shallow clone with a limited history depth.
#[arg(long, value_name = "DEPTH")]
pub git_depth: Option<u32>,
// --- Filtering Options ---
/// Maximum file size to include (e.g., "1M", "512k", "1024"). Files larger than this are skipped.
#[arg(short = 'm', long, value_name = "BYTES")]
pub max_size: Option<String>, // Will be parsed into u64 later
/// Do not recurse into subdirectories. Process only the top-level directory or the specified file.
#[arg(short = 'n', long, action = clap::ArgAction::SetTrue)]
pub no_recursive: bool,
/// Include only files with these extensions (case-insensitive). Can be specified multiple times.
#[arg(short = 'e', long = "ext", value_name = "EXT", num_args = 1..)]
pub extensions: Option<Vec<String>>,
/// Exclude files with these extensions (case-insensitive). Can be specified multiple times.
#[arg(short = 'x', long = "exclude-ext", value_name = "EXT", num_args = 1..)]
pub exclude_extensions: Option<Vec<String>>,
/// Ignore files or directories matching these glob patterns (relative to input path). Can be specified multiple times.
#[arg(short = 'i', long = "ignore", value_name = "GLOB", num_args = 1..)]
pub ignore_patterns: Option<Vec<String>>,
/// Include only files whose full path matches any of these regular expressions (case-insensitive).
#[arg(short = 'r', long = "regex", value_name = "REGEX", num_args = 1..)]
pub path_regex: Option<Vec<String>>,
/// Include only files whose filename (basename) matches any of these regular expressions (case-insensitive).
#[arg(short = 'd', long = "filename-regex", value_name = "REGEX", num_args = 1..)]
pub filename_regex: Option<Vec<String>>,
/// Do not respect .gitignore, .ignore, or other VCS ignore files. Process all files found.
#[arg(short = 't', long, action = clap::ArgAction::SetTrue)]
pub no_gitignore: bool,
/// Include files detected as binary/non-text (default is to skip them).
#[arg(short = 'B', long, action = clap::ArgAction::SetTrue)] // <-- ADDED short = 'B'
pub include_binary: bool,
/// Skip common lockfiles (e.g., Cargo.lock, package-lock.json).
#[arg(short = 'K', long, action = clap::ArgAction::SetTrue)] // <-- ADDED short = 'K'
pub no_lockfiles: bool,
// --- Content Processing Options ---
/// Remove C/C++ style comments (// and /* ... */) from the output.
#[arg(short = 'c', long, action = clap::ArgAction::SetTrue)]
pub remove_comments: bool,
/// Remove empty lines (containing only whitespace) from the output.
#[arg(short = 'l', long, action = clap::ArgAction::SetTrue)]
pub remove_empty_lines: bool,
// --- Output Formatting Options ---
/// Only include the filename (basename) in the '## File:' header, not the full relative path.
#[arg(short = 'f', long, action = clap::ArgAction::SetTrue)]
pub filename_only: bool,
/// Add line numbers (N | ) to the beginning of each line in the code blocks.
#[arg(short = 'L', long, action = clap::ArgAction::SetTrue)]
pub line_numbers: bool,
/// Wrap filenames in the '## File:' header and summary list with backticks (`).
#[arg(short = 'b', long, action = clap::ArgAction::SetTrue)]
pub backticks: bool,
// --- Output Destination & Summary ---
/// Write the output to the specified file instead of stdout.
#[arg(short = 'o', long, value_name = "FILE")]
pub output_file: Option<String>, // Using String, convert to PathBuf later
/// Copy the output to the system clipboard instead of printing to stdout or a file.
#[arg(short = 'p', long, action = clap::ArgAction::SetTrue)]
pub paste: bool,
/// Print a summary list of processed files at the end of the output.
#[arg(short = 's', long, action = clap::ArgAction::SetTrue)]
pub summary: bool,
/// Include line, character (byte), and word counts in the summary (implies -s).
#[arg(short = 'C', long, action = clap::ArgAction::SetTrue, requires = "summary")]
// <-- ADDED short = 'C'
pub counts: bool,
// --- Processing Order ---
/// Process files matching these glob patterns (relative path/filename) last, in the order specified.
#[arg(short = 'z', long = "last", value_name = "GLOB", num_args = 1..)]
pub process_last: Option<Vec<String>>,
/// Only process the files specified with -z/--last. Skip all other files.
#[arg(short = 'Z', long, action = clap::ArgAction::SetTrue, requires = "process_last")]
pub only_last: bool,
// --- Execution Control ---
/// Perform a dry run. Print the files that would be processed (respecting filters and order) but not their content.
#[arg(short = 'D', long, action = clap::ArgAction::SetTrue)]
pub dry_run: bool,
}