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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
//! Command-line interface definitions.
use std::path::PathBuf;
use clap::{Parser, Subcommand, ValueEnum};
use crate::path_source::Target;
#[derive(Debug, Parser)]
#[command(name = "pathlint", version, about = "Lint PATH against [[expect]] rules", long_about = None)]
pub struct Cli {
#[command(subcommand)]
pub command: Option<Command>,
#[command(flatten)]
pub global: GlobalOpts,
}
#[derive(Debug, Subcommand)]
pub enum Command {
/// Lint PATH against expectations (default).
Check,
/// Write a starter `pathlint.toml` in the current directory.
Init(InitArgs),
/// Inspect the source catalog.
Catalog {
#[command(subcommand)]
action: CatalogCommand,
},
/// Lint the PATH itself (duplicates, missing dirs, env-var
/// shortening candidates, Windows 8.3 short names, malformed
/// entries). Independent of `[[expect]]` rules.
Doctor(DoctorArgs),
/// Show where a command resolves from, which sources it matches,
/// and the most plausible uninstall command.
Where(WhereArgs),
}
#[derive(Debug, clap::Args)]
pub struct WhereArgs {
/// The command to look up on PATH.
pub command: String,
/// Emit machine-readable JSON instead of the default human
/// output. The schema is described in the README; provenance
/// and uninstall objects use a `kind` discriminator so consumers
/// can match on it.
#[arg(long)]
pub json: bool,
}
#[derive(Debug, clap::Args)]
pub struct DoctorArgs {
/// Only show diagnostics whose kind matches one of the listed
/// values. Mutually exclusive with `--exclude`. Accepts a comma
/// or repeated flag form: `--include duplicate,missing` or
/// `--include duplicate --include missing`.
#[arg(long, value_delimiter = ',', conflicts_with = "exclude")]
pub include: Vec<String>,
/// Suppress diagnostics whose kind matches one of the listed
/// values. Affects exit code too: an excluded `Malformed` no
/// longer escalates to exit 1.
#[arg(long, value_delimiter = ',')]
pub exclude: Vec<String>,
}
#[derive(Debug, Subcommand)]
pub enum CatalogCommand {
/// List every known source — built-in plus any defined in
/// `pathlint.toml` — with its description and per-OS path.
List(CatalogListArgs),
}
#[derive(Debug, clap::Args)]
pub struct CatalogListArgs {
/// Show every per-OS path of each source, not just the one for
/// the running OS.
#[arg(long)]
pub all: bool,
/// Print only source names, one per line.
#[arg(long)]
pub names_only: bool,
}
#[derive(Debug, clap::Args)]
pub struct InitArgs {
/// Also embed the entire built-in source catalog so users can
/// edit per-OS paths field by field. Off by default to keep the
/// starter file short.
#[arg(long)]
pub emit_defaults: bool,
/// Overwrite an existing `pathlint.toml` if one is already present.
#[arg(long)]
pub force: bool,
}
#[derive(Debug, clap::Args)]
pub struct GlobalOpts {
/// PATH source: process (default) / user / machine. user / machine
/// are Windows-only.
#[arg(long, value_enum, default_value_t = TargetArg::Process)]
pub target: TargetArg,
/// Path to pathlint.toml. Default search: ./pathlint.toml then
/// $XDG_CONFIG_HOME/pathlint/pathlint.toml.
#[arg(long)]
pub rules: Option<PathBuf>,
/// Print every expectation incl. n/a, plus the resolved PATH.
#[arg(short, long)]
pub verbose: bool,
/// Only print failures.
#[arg(short, long)]
pub quiet: bool,
/// Color output.
#[arg(long, value_enum, default_value_t = ColorArg::Auto)]
pub color: ColorArg,
/// ASCII-only output.
#[arg(long)]
pub no_glyphs: bool,
}
#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum TargetArg {
Process,
User,
Machine,
}
impl From<TargetArg> for Target {
fn from(t: TargetArg) -> Self {
match t {
TargetArg::Process => Target::Process,
TargetArg::User => Target::User,
TargetArg::Machine => Target::Machine,
}
}
}
#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum ColorArg {
Auto,
Always,
Never,
}