pub use crate::tool_schema::ToolSchemaFormat;
use clap::Parser;
mod analysis;
mod badge;
mod check_ignore;
mod cockpit;
mod commands;
mod completions;
mod context;
mod diff;
mod export;
mod gate;
mod global;
mod init;
mod lang;
mod module;
mod run;
mod sensor;
mod tools;
mod value_enums;
pub use analysis::{
AnalysisPreset, CliAnalyzeArgs, EffortLayer, EffortModelKind, ImportGranularity, NearDupScope,
};
pub use badge::{BadgeArgs, BadgeMetric};
pub use check_ignore::CliCheckIgnoreArgs;
pub use cockpit::{BaselineArgs, CockpitArgs, CockpitFormat, DiffRangeMode};
pub use commands::Commands;
pub use completions::{CompletionsArgs, Shell};
pub use context::{
CliContextArgs, ContextOutput, ContextStrategy, HandoffArgs, HandoffPreset, ValueMetric,
};
pub use diff::{ColorMode, DiffArgs, DiffFormat};
pub use export::CliExportArgs;
pub use gate::{CliGateArgs, GateFormat};
pub use global::GlobalArgs;
pub use init::{InitArgs, InitProfile};
pub use lang::CliLangArgs;
pub use module::CliModuleArgs;
pub use run::RunArgs;
pub use sensor::{SensorArgs, SensorFormat};
pub use tools::ToolsArgs;
pub use value_enums::{
AnalysisFormat, ChildIncludeMode, ChildrenMode, ConfigMode, ExportFormat, RedactMode,
TableFormat,
};
#[derive(Parser, Debug)]
#[command(name = "tokmd", version, long_about = None)]
pub struct Cli {
#[command(flatten)]
pub global: GlobalArgs,
#[command(flatten)]
pub lang: CliLangArgs,
#[command(subcommand)]
pub command: Option<Commands>,
#[arg(long, visible_alias = "view", global = true)]
pub profile: Option<String>,
}
pub use tokmd_settings::{
AnalyzeConfig, BadgeConfig, ContextConfig, ExportConfig, GateConfig, GateRule, ModuleConfig,
Profile, RatchetRuleConfig, ScanConfig, TomlConfig, TomlResult, UserConfig, ViewProfile,
};
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn user_config_default_is_empty() {
let c = UserConfig::default();
assert!(c.profiles.is_empty());
assert!(c.repos.is_empty());
}
#[test]
fn profile_default_all_none() {
let p = Profile::default();
assert!(p.format.is_none());
assert!(p.top.is_none());
assert!(p.files.is_none());
assert!(p.module_roots.is_none());
assert!(p.module_depth.is_none());
assert!(p.min_code.is_none());
assert!(p.max_rows.is_none());
assert!(p.redact.is_none());
assert!(p.meta.is_none());
assert!(p.children.is_none());
}
#[test]
fn cli_lang_args_default() {
let a = CliLangArgs::default();
assert!(a.paths.is_none());
assert!(a.format.is_none());
assert!(a.top.is_none());
assert!(!a.files);
assert!(a.children.is_none());
}
#[test]
fn context_strategy_default_is_greedy() {
assert_eq!(ContextStrategy::default(), ContextStrategy::Greedy);
}
#[test]
fn value_metric_default_is_code() {
assert_eq!(ValueMetric::default(), ValueMetric::Code);
}
#[test]
fn context_output_default_is_list() {
assert_eq!(ContextOutput::default(), ContextOutput::List);
}
#[test]
fn cockpit_format_default_is_json() {
assert_eq!(CockpitFormat::default(), CockpitFormat::Json);
}
#[test]
fn handoff_preset_default_is_risk() {
assert_eq!(HandoffPreset::default(), HandoffPreset::Risk);
}
#[test]
fn diff_range_mode_default_is_two_dot() {
assert_eq!(DiffRangeMode::default(), DiffRangeMode::TwoDot);
}
#[test]
fn context_strategy_uses_kebab_case() {
assert_eq!(
serde_json::to_string(&ContextStrategy::Greedy).unwrap(),
"\"greedy\""
);
assert_eq!(
serde_json::to_string(&ContextStrategy::Spread).unwrap(),
"\"spread\""
);
}
#[test]
fn value_metric_uses_kebab_case() {
assert_eq!(
serde_json::to_string(&ValueMetric::Hotspot).unwrap(),
"\"hotspot\""
);
}
#[test]
fn user_config_serde_roundtrip() {
let mut c = UserConfig::default();
c.profiles.insert(
"llm_safe".into(),
Profile {
format: Some("json".into()),
top: Some(10),
redact: Some(tokmd_types::RedactMode::All),
..Profile::default()
},
);
c.repos.insert("owner/repo".into(), "llm_safe".into());
let json = serde_json::to_string(&c).unwrap();
let back: UserConfig = serde_json::from_str(&json).unwrap();
assert_eq!(back.profiles.len(), 1);
assert_eq!(back.repos.len(), 1);
assert_eq!(back.profiles["llm_safe"].top, Some(10));
}
}