feat(wave1): Define global CLI flags (OutputFormat, IncludeList) [claudbg-nmuu]
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>main
parent
1a2f999636
commit
ded9cd3a5c
@ -1,11 +1,12 @@
|
||||
---
|
||||
# claudbg-nmuu
|
||||
title: Define global CLI flags
|
||||
status: todo
|
||||
status: completed
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-03-27T19:38:56Z
|
||||
updated_at: 2026-03-27T19:38:56Z
|
||||
updated_at: 2026-03-28T04:25:33Z
|
||||
parent: claudbg-h7xu
|
||||
---
|
||||
|
||||
Add global flags available to all subcommands: --output [table|json|xml] (default: table), --verbose (bool), --include <list> (comma-separated: thinking,output,tools — default: tools). These must be accessible from every command handler.
|
||||
Created src/cli.rs with OutputFormat enum (Table/Json/Xml, derives Default+ValueEnum), IncludeList struct (thinking, output bools, derives Default), and FromStr impl for IncludeList that parses comma-separated tokens and returns AppError::InvalidArg for unknowns. Six unit tests cover empty string, single tokens, both tokens, unknown token error, and whitespace trimming. Updated src/lib.rs to declare pub mod cli.
|
||||
|
||||
@ -0,0 +1,107 @@
|
||||
//! CLI types: output format, include list, and global options.
|
||||
|
||||
/// Output format for all commands.
|
||||
#[derive(Debug, Clone, Default, clap::ValueEnum)]
|
||||
pub enum OutputFormat {
|
||||
/// Human-readable table (default).
|
||||
#[default]
|
||||
Table,
|
||||
/// JSON output.
|
||||
Json,
|
||||
/// XML output.
|
||||
Xml,
|
||||
}
|
||||
|
||||
/// Comma-separated list of optional content to include in transcripts.
|
||||
///
|
||||
/// Accepted tokens: `thinking`, `output`.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct IncludeList {
|
||||
/// Include `thinking` blocks in transcripts.
|
||||
pub thinking: bool,
|
||||
/// Include tool `output` blocks in transcripts.
|
||||
pub output: bool,
|
||||
}
|
||||
|
||||
impl std::str::FromStr for IncludeList {
|
||||
type Err = crate::error::AppError;
|
||||
|
||||
/// Parse a comma-separated string of include tokens.
|
||||
///
|
||||
/// Accepted tokens: `thinking`, `output`.
|
||||
/// Returns [`AppError::InvalidArg`] for any unknown token.
|
||||
fn from_str(s: &str) -> crate::error::Result<Self> {
|
||||
let mut list = IncludeList::default();
|
||||
for token in s.split(',') {
|
||||
let token = token.trim();
|
||||
if token.is_empty() {
|
||||
continue;
|
||||
}
|
||||
match token {
|
||||
"thinking" => list.thinking = true,
|
||||
"output" => list.output = true,
|
||||
other => {
|
||||
return Err(crate::error::AppError::InvalidArg(format!(
|
||||
"unknown include token: {other}"
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(list)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::str::FromStr;
|
||||
|
||||
/// Empty string produces a default `IncludeList` with both flags false.
|
||||
#[test]
|
||||
fn include_list_empty_string() {
|
||||
let list = IncludeList::from_str("").unwrap();
|
||||
assert!(!list.thinking);
|
||||
assert!(!list.output);
|
||||
}
|
||||
|
||||
/// Parsing `"thinking"` sets the thinking flag only.
|
||||
#[test]
|
||||
fn include_list_thinking_only() {
|
||||
let list = IncludeList::from_str("thinking").unwrap();
|
||||
assert!(list.thinking);
|
||||
assert!(!list.output);
|
||||
}
|
||||
|
||||
/// Parsing `"output"` sets the output flag only.
|
||||
#[test]
|
||||
fn include_list_output_only() {
|
||||
let list = IncludeList::from_str("output").unwrap();
|
||||
assert!(!list.thinking);
|
||||
assert!(list.output);
|
||||
}
|
||||
|
||||
/// Parsing `"thinking,output"` sets both flags.
|
||||
#[test]
|
||||
fn include_list_both() {
|
||||
let list = IncludeList::from_str("thinking,output").unwrap();
|
||||
assert!(list.thinking);
|
||||
assert!(list.output);
|
||||
}
|
||||
|
||||
/// An unknown token returns an `AppError::InvalidArg`.
|
||||
#[test]
|
||||
fn include_list_unknown_token() {
|
||||
let result = IncludeList::from_str("images");
|
||||
assert!(result.is_err());
|
||||
let msg = result.unwrap_err().to_string();
|
||||
assert!(msg.contains("unknown include token: images"), "got: {msg}");
|
||||
}
|
||||
|
||||
/// Whitespace around tokens is trimmed.
|
||||
#[test]
|
||||
fn include_list_whitespace_trim() {
|
||||
let list = IncludeList::from_str(" thinking , output ").unwrap();
|
||||
assert!(list.thinking);
|
||||
assert!(list.output);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue