Open12
issue_tracker dev log

clapでサブコマンドを実装

参考になりそう

#[derive(Debug, Subcommand)]をつけたenumでサブコマンドのリストを定義して、各コマンドはstructで定義、そのstructをenumで定義したコマンドリストの値として使用?

#[derive(Debug, Parser)]
struct Args {
#[command(subcommand)]
subcommand: Commands,
}
#[derive(Debug, Subcommand)]
enum Commands {
#[clap(arg_required_else_help = true)]
Init(Init),
Create,
Delete,
List,
Comment,
}
#[derive(Debug, Parser)]
struct Init {
name: String,
}

バージョンのせいか、見るサイトで全部実装方法が違う気がする

#[derive(Parser)]
#[command(version, about, long_about = None)]
struct Cli {
/// Optional name to operate on
name: Option<String>,
/// Sets a custom config file
#[arg(short, long, value_name = "FILE")]
config: Option<PathBuf>,
/// Turn debugging information on
#[arg(short, long, action = clap::ArgAction::Count)]
debug: u8,
#[command(subcommand)]
command: Option<Commands>,
}
#[derive(Subcommand)]
enum Commands {
/// does testing things
Test {
/// lists test values
#[arg(short, long)]
list: bool,
},
}
docsではenumの中でサブコマンドの中身を定義してる

サブコマンドの話: スクラップが散るのでここに返信することに

use clap::{Args, Parser, Subcommand};
#[derive(Parser)]
#[command(version, about, long_about = None)]
#[command(propagate_version = true)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
/// Adds files to myapp
Add(AddArgs),
}
#[derive(Args)]
struct AddArgs {
name: Option<String>,
}
fn main() {
let cli = Cli::parse();
// You can check for the existence of subcommands, and if found use their
// matches just as you would the top level cmd
match &cli.command {
Commands::Add(name) => {
println!("'myapp add' was used, name is: {:?}", name.name);
}
}
}
structに分ける方法もdocsにあった

一旦以下で進める
まだオプションとかは追加するだろうけど、一旦は
#[derive(Debug, Parser)]
#[command(propagate_version = true)]
#[command(name = "cpls")]
struct Cli {
#[command(subcommand)]
subcommand: Commands,
}
#[derive(Debug, Subcommand)]
enum Commands {
#[clap(arg_required_else_help = true)]
Init(Init),
Create(Create),
Delete(Delete),
List(List),
Comment(Comment),
}
#[derive(Debug, Args)]
struct Init {
name: Option<String>,
#[arg(short = 'p', long = "path")]
path: Option<String>,
}
#[derive(Debug, Args)]
struct Create {
name: String,
}
#[derive(Debug, Args)]
struct Delete {
issue_num: u64,
}
#[derive(Debug, Args)]
struct List {}
#[derive(Debug, Args)]
struct Comment {
issue_num: u64,
comment: String,
}

deriveのParserとArgsって何だ?
Argsはサブコマンドとかの引数をまとめてstructで管理するためのマクロで、Parserはルートの処理用。らしい?

名前はchatGPTに出させて、CodePulse
コマンド名は略してcpls
「CodePulse」は、私が提案した造語のひとつで、以下のような意味やイメージを込めています:
🌟 名前の構成
- Code(コード):プログラム、ソースコード、開発作業全体を示す
- Pulse(脈拍・鼓動):活動のリズム、変化の兆し、定期的な更新、進捗の波などを象徴
💡 想定されるニュアンス
「CodePulse」は、「コードの鼓動を感じながら、開発の進捗や問題をリアルタイムで捉えるツール」というような雰囲気を意図しています。
🧑💻 こんな用途に合いそう
- ローカルで稼働する軽量なタスク・Issue管理ツール
- コードの変更や進捗の「鼓動」を記録・可視化したい用途
- GitHubの代替というより、プライベートで開発に寄り添うようなアプリ
🔤 発音・響き
- 覚えやすく、テックっぽさもあり、英語圏でも通用する
- ドメイン名やCLIコマンド名にも使いやすい(例:
codepulse init
)
だそうです

こんなこともできるんだ
match cli.subcommand {
Commands::Init(init) => todo!(),
other => {
match other {
Commands::Init(init) => todo!(),
Commands::Create(create) => todo!(),
Commands::Delete(delete) => todo!(),
Commands::List(list) => todo!(),
Commands::Comment(comment) => todo!(),
}
}
}