diff --git a/CHANGELOG.md b/CHANGELOG.md index 377d98cb..41078df6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `git-remote-rad` now correctly reports the default branch to Git by listing the symbolic reference `HEAD`. - `rad status` learned a new option `--only nid` for printing the Node ID. +- `rad issue` now uses `clap` to parse its command-line arguments. + This affects error reporting as well as help output. ## Fixed Bugs diff --git a/crates/radicle-cli/examples/rad-issue-list.md b/crates/radicle-cli/examples/rad-issue-list.md new file mode 100644 index 00000000..a3cfdf8c --- /dev/null +++ b/crates/radicle-cli/examples/rad-issue-list.md @@ -0,0 +1,62 @@ +Let's say we have a project with an issue created already. We can list all open issues. + +``` +$ rad issue list +╭────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ ● ID Title Author Labels Assignees Opened │ +├────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ ● d87dcfe flux capacitor underpowered alice (you) good-first-issue now │ +╰────────────────────────────────────────────────────────────────────────────────────────────────────╯ +``` + +We can now assign ourselves to the open issue. + +``` +$ rad issue assign d87dcfe --add did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --no-announce +``` + +It will now also show up in the list of issues assigned to us. + +``` +$ rad issue list --assigned me +╭────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ ● ID Title Author Labels Assignees Opened │ +├────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ ● d87dcfe flux capacitor underpowered alice (you) good-first-issue alice now │ +╰────────────────────────────────────────────────────────────────────────────────────────────────────╯ +``` + +If we now fix this issue, we can close it. + +``` +$ rad issue state --solved d87dcfe --no-announce +✓ Issue d87dcfe is now solved +``` + +It will not show up in the list of open issues anymore. + +``` +$ rad issue list +``` + +Instead, it will now show up in the list of solved issues. + +``` +$ rad issue list --solved +╭────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ ● ID Title Author Labels Assignees Opened │ +├────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ ● d87dcfe flux capacitor underpowered alice (you) good-first-issue alice now │ +╰────────────────────────────────────────────────────────────────────────────────────────────────────╯ +``` + +Note: You can achieve the same by omitting the `list` subcommand, since that's the fallback when no subcommand is specified. + +``` +$ rad issue --solved +╭────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ ● ID Title Author Labels Assignees Opened │ +├────────────────────────────────────────────────────────────────────────────────────────────────────┤ +│ ● d87dcfe flux capacitor underpowered alice (you) good-first-issue alice now │ +╰────────────────────────────────────────────────────────────────────────────────────────────────────╯ +``` diff --git a/crates/radicle-cli/src/commands/help.rs b/crates/radicle-cli/src/commands/help.rs index a4c6d85a..26c40497 100644 --- a/crates/radicle-cli/src/commands/help.rs +++ b/crates/radicle-cli/src/commands/help.rs @@ -10,33 +10,62 @@ pub const HELP: Help = Help { usage: "Usage: rad help [--help]", }; -const COMMANDS: &[Help] = &[ - crate::commands::auth::HELP, - crate::commands::block::HELP, - crate::commands::checkout::HELP, - crate::commands::clone::HELP, - crate::commands::config::HELP, - crate::commands::fork::HELP, - crate::commands::help::HELP, - crate::commands::id::HELP, - crate::commands::init::HELP, - crate::commands::inbox::HELP, - crate::commands::inspect::HELP, - crate::commands::issue::HELP, - crate::commands::ls::HELP, - crate::commands::node::HELP, - crate::commands::patch::HELP, - crate::commands::path::HELP, - crate::commands::clean::HELP, - crate::commands::rad_self::HELP, - crate::commands::seed::HELP, - crate::commands::follow::HELP, - crate::commands::unblock::HELP, - crate::commands::unfollow::HELP, - crate::commands::unseed::HELP, - crate::commands::remote::HELP, - crate::commands::stats::HELP, - crate::commands::sync::HELP, +enum CommandItem { + Lexopt(Help), + Clap { + name: &'static str, + about: &'static str, + }, +} + +impl CommandItem { + fn name(&self) -> &str { + match self { + CommandItem::Lexopt(help) => help.name, + CommandItem::Clap { name, .. } => name, + } + } + + fn description(&self) -> &str { + match self { + CommandItem::Lexopt(help) => help.description, + CommandItem::Clap { + about: description, .. + } => description, + } + } +} + +const COMMANDS: &[CommandItem] = &[ + CommandItem::Lexopt(crate::commands::auth::HELP), + CommandItem::Lexopt(crate::commands::block::HELP), + CommandItem::Lexopt(crate::commands::checkout::HELP), + CommandItem::Lexopt(crate::commands::clone::HELP), + CommandItem::Lexopt(crate::commands::config::HELP), + CommandItem::Lexopt(crate::commands::fork::HELP), + CommandItem::Lexopt(crate::commands::help::HELP), + CommandItem::Lexopt(crate::commands::id::HELP), + CommandItem::Lexopt(crate::commands::init::HELP), + CommandItem::Lexopt(crate::commands::inbox::HELP), + CommandItem::Lexopt(crate::commands::inspect::HELP), + CommandItem::Clap { + name: "issue", + about: crate::commands::issue::ABOUT, + }, + CommandItem::Lexopt(crate::commands::ls::HELP), + CommandItem::Lexopt(crate::commands::node::HELP), + CommandItem::Lexopt(crate::commands::patch::HELP), + CommandItem::Lexopt(crate::commands::path::HELP), + CommandItem::Lexopt(crate::commands::clean::HELP), + CommandItem::Lexopt(crate::commands::rad_self::HELP), + CommandItem::Lexopt(crate::commands::seed::HELP), + CommandItem::Lexopt(crate::commands::follow::HELP), + CommandItem::Lexopt(crate::commands::unblock::HELP), + CommandItem::Lexopt(crate::commands::unfollow::HELP), + CommandItem::Lexopt(crate::commands::unseed::HELP), + CommandItem::Lexopt(crate::commands::remote::HELP), + CommandItem::Lexopt(crate::commands::stats::HELP), + CommandItem::Lexopt(crate::commands::sync::HELP), ]; #[derive(Default)] @@ -79,8 +108,8 @@ pub fn run(_options: Options, ctx: impl term::Context) -> anyhow::Result<()> { for help in COMMANDS { term::info!( "\t{} {}", - term::format::bold(format!("{:-12}", help.name)), - term::format::dim(help.description) + term::format::bold(format!("{:-12}", help.name())), + term::format::dim(help.description()) ); } term::blank(); diff --git a/crates/radicle-cli/src/commands/issue.rs b/crates/radicle-cli/src/commands/issue.rs index db8a50f6..554bb2b1 100644 --- a/crates/radicle-cli/src/commands/issue.rs +++ b/crates/radicle-cli/src/commands/issue.rs @@ -1,582 +1,124 @@ +mod args; mod cache; +mod comment; -use std::collections::BTreeSet; -use std::ffi::OsString; -use std::str::FromStr; +use anyhow::Context as _; -use anyhow::{anyhow, Context as _}; - -use radicle::cob::common::{Label, Reaction}; +use radicle::cob::common::Label; use radicle::cob::issue::{CloseReason, State}; -use radicle::cob::{issue, thread, Title}; +use radicle::cob::{issue, Title}; + use radicle::crypto; -use radicle::git::Oid; use radicle::issue::cache::Issues as _; use radicle::node::device::Device; use radicle::node::NodeId; -use radicle::prelude::{Did, RepoId}; +use radicle::prelude::Did; use radicle::profile; use radicle::storage; -use radicle::storage::{ReadRepository, WriteRepository, WriteStorage}; +use radicle::storage::{WriteRepository, WriteStorage}; use radicle::Profile; use radicle::{cob, Node}; +pub use args::Args; +use args::{Assigned, Command, CommentAction, StateArg}; + use crate::git::Rev; use crate::node; use crate::terminal as term; -use crate::terminal::args::{Args, Error, Help}; +use crate::terminal::args::Error; use crate::terminal::format::Author; use crate::terminal::issue::Format; -use crate::terminal::patch::Message; use crate::terminal::Element; -pub const HELP: Help = Help { - name: "issue", - description: "Manage issues", - version: env!("RADICLE_VERSION"), - usage: r#" -Usage +pub const ABOUT: &str = "Manage issues"; - rad issue [