동작하는 코드
clap 크레이트는 derive 매크로를 제공해 복잡한 CLI도 선언적으로 정의할 수 있게 해줍니다.
use clap::{Parser, Subcommand};
#[derive(Parser, Debug)]
#[command(name = "todo", version, about = "작고 빠른 CLI TODO", long_about = None)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand, Debug)]
enum Commands {
/// 새 할 일을 추가합니다
Add {
#[arg(value_name = "TEXT")]
text: String,
},
/// 할 일을 완료 처리합니다
Done {
#[arg(value_name = "ID")]
id: u32,
},
/// 목록을 출력합니다
List {
#[arg(long, help = "완료된 항목도 포함")]
all: bool,
},
}
fn main() {
let cli = Cli::parse();
match cli.command {
Commands::Add { text } => println!("추가: {text}"),
Commands::Done { id } => println!("완료 처리: #{id}"),
Commands::List { all } => println!("목록 출력 (all={all})"),
}
}
Cli::parse()가 자동으로std::env::args()를 읽고 검증한 뒤 구조체에 채워 넣어요.#[command(version)]을 붙이면--version플래그를,about을 채우면--help에 설명이 자동으로 들어갑니다.
도움말과 에러 메시지
$ todo --help
Usage: todo <COMMAND>
Commands:
add 새 할 일을 추가합니다
done 할 일을 완료 처리합니다
list 목록을 출력합니다
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help (see more with '--help')
-V, --version Print version
잘못된 인자를 입력하면 clap이 친절한 메시지와 함께 non-zero exit code로 종료합니다.
$ todo add
? failed to parse argument: TEXT is required but missing
직접 해보기
todo list --all처럼--all을 붙였을 때 true, 생략하면 false가 되도록 기본값을 다뤄 보세요.todo done --id 3처럼 long 옵션/short 옵션을 섞어서 사용하는 subcommand를 하나 더 추가해 보세요.clap::Parser::command().long_about("...")를 활용해 README 수준의 자세한 도움말을 붙여 보세요.
- 환경 변수와 함께 사용 —
#[arg(env = "TODO_PATH")]속성을 사용해 저장 경로를 환경 변수로도 받을 수 있도록 CLI를 확장해 보세요. - exit 코드 제어 — 비정상적인 상황에서
eprintln!으로 메시지를 출력하고std::process::exit(1)로 종료하는 패턴을 추가해 보세요. - config 서브커맨드 —
todo config set --key theme --value dark같은 하위 명령을 설계하고,serde로 설정 파일을 저장하는 로직과 연결해 보세요.