Skip to main content

coding_tools/cli/
ct_survey.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 Jonathan Shook
3
4//! The `ct-survey` command grammar (see [`crate::cli`]); the `ct-survey` bin is a
5//! thin parse-and-dispatch wrapper over this `Cli`.
6
7use std::path::PathBuf;
8
9use clap::Parser;
10
11use crate::explain::Format;
12use crate::pulse::HeartbeatOpts;
13use crate::survey::{Depth, GroupKind, SortKey};
14
15#[derive(Parser, Debug)]
16#[command(
17    name = "ct-survey",
18    version,
19    about = "Survey a codebase by its build-system units: crates and modules, with file/line/test counts.",
20    long_about = "ct-survey reports a format-contextualized survey of a codebase (also reachable as \
21                  `ct survey`): for Rust, the workspace -> crate -> module hierarchy, each element \
22                  carrying file, line, and test counts. Crate identity, workspace membership, and \
23                  cargo target kinds are authoritative (read from `cargo metadata`); file/line counts \
24                  are exact; the module bucketing and the #[test] tally are heuristic (marked ~ in the \
25                  output). With no --group, the contextual group type is inferred from the given path's \
26                  Cargo.toml (a [workspace] table vs a lone [package]). See `ct-survey --explain` for \
27                  agent-oriented documentation."
28)]
29pub struct Cli {
30    /// Path to survey: a directory, or a Cargo.toml. Defaults to the current directory.
31    #[arg(default_value = ".")]
32    pub path: PathBuf,
33
34    /// Contextual group type; inferred from the path's Cargo.toml when omitted.
35    #[arg(long, value_enum)]
36    pub group: Option<GroupKind>,
37
38    /// How deep to descend: crate (per-crate only) or module (per-crate then per-module).
39    #[arg(long, value_enum, default_value_t = Depth::Module)]
40    pub depth: Depth,
41
42    /// Sort crates and modules by this key: name (ascending) or files/lines/tests (largest first).
43    #[arg(long, value_enum, default_value_t = SortKey::Name)]
44    pub sort: SortKey,
45
46    /// Emit a structured JSON result instead of text.
47    #[arg(long)]
48    pub json: bool,
49
50    /// Like `--json`, but pretty-printed (indented).
51    #[arg(long)]
52    pub json_pretty: bool,
53
54    /// Abort with exit 2 if the run exceeds SECS seconds (fractional allowed).
55    #[arg(long, value_name = "SECS")]
56    pub timeout: Option<f64>,
57
58    #[command(flatten)]
59    pub heartbeat: HeartbeatOpts,
60
61    /// Print agent usage docs (md or json) and exit.
62    #[arg(long, value_enum, num_args = 0..=1, default_missing_value = "md")]
63    pub explain: Option<Format>,
64}