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
|
# claudbg-nmuu
|
||||||
title: Define global CLI flags
|
title: Define global CLI flags
|
||||||
status: todo
|
status: completed
|
||||||
type: task
|
type: task
|
||||||
|
priority: normal
|
||||||
created_at: 2026-03-27T19:38:56Z
|
created_at: 2026-03-27T19:38:56Z
|
||||||
updated_at: 2026-03-27T19:38:56Z
|
updated_at: 2026-03-28T04:25:33Z
|
||||||
parent: claudbg-h7xu
|
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