cli: `rad patch --help` opens man page

This is the same behavior as `git`. We also update the man page to have
the full list of commands and flags.
This commit is contained in:
cloudhead 2023-08-31 13:31:58 +02:00
parent b1213931de
commit 8d5299fe85
No known key found for this signature in database
5 changed files with 99 additions and 18 deletions

View File

@ -12,7 +12,16 @@ rad-patch - Manage radicle patches.
== Synopsis
*rad patch* *
*rad patch* [<option>...] +
*rad patch* _list_ [--all|--merged|--open|--archived|--draft] [<option>...] +
*rad patch* _show_ <patch-id> [<option>...] +
*rad patch* _archive_ <patch-id> [<option>...] +
*rad patch* _update_ <patch-id> [<option>...] +
*rad patch* _checkout_ <patch-id> [<option>...] +
*rad patch* _delete_ <patch-id> [<option>...] +
*rad patch* _redact_ <revision-id> [<option>...] +
*rad patch* _ready_ <patch-id> [--undo] [<option>...] +
*rad patch* _edit_ <patch-id> [<option>...] +
== Description
@ -20,13 +29,64 @@ The Radicle *patch* command is used for managing changesets inside of Radicle
repositories.
Though many actions can be performed using *rad patch*, certain patch-related
actions require using *git* directly. For example, opening a patch is typically
actions use *git* directly. For example, opening a patch is typically
done using *git push*, while merging a patch is done with a combination of
*git merge* and *git push*.
To make this possible, Radicle ships with a helper program, *git-remote-rad*
which is invoked by *git* on push and fetch to and from Radicle remotes.
== Commands
With no arguments, *rad patch* defaults to the _list_ command, showing the list of
open patches for the current repository.
=== show
Shows information on the given patch.
*<patch-id>*:: The patch to show
*--patch*, *-p*:: Show the patch changes in git patch format
*--verbose*, *-v*:: Show additional information about the patch
=== edit
Edits a patch revision comment. To edit the patch title or description, pass
in the *<patch-id>*. To edit a revision comment, pass that revision's
*<revision-id>*.
*<revision-id>*::
The revision to edit.
*--message*, *-m [<string>]*::
Comment message to the patch or revision. If omitted, Radicle will prompt for
a comment string via *$EDITOR*.
=== list
List patches in the current repository. The default is *--open*.
*--all*:: List all patches, including merged and archived patches
*--archived*:: List only archived patches
*--merged*:: List only merged patches
*--open*:: List only open patches
*--draft*:: List only draft patches
=== ready
Mark a patch as ready to review. This changes the state of a patch from *draft*
to *open*.
*--undo*:: Change a patch back to *draft*
=== update
Updates a patch to the current repository *HEAD*. This is a low-level command
that should only be used when using *git push rad* is not possible.
*--message*, *-m [<string>]*:: Provide a comment message to the revision
*--no-message*:: Leave the revision comment message blank
== Opening a patch
To open a patch, we start by making changes to our working copy, typically on
@ -148,7 +208,3 @@ our master branch. Then we pushed to our *rad* remote.
To list patches, run *rad patch*. By default, this will only show open patches.
To list all patches, including ones that have been merged or archived, add the
*--all* option.
== Other patch commands
For a full list of patch sub-commands, run *rad patch --help*.

View File

@ -242,7 +242,10 @@ impl Args for Options {
Long("verbose") | Short('v') => {
verbose = true;
}
Long("help") | Short('h') => {
Long("help") => {
return Err(Error::HelpManual.into());
}
Short('h') => {
return Err(Error::Help.into());
}

View File

@ -76,28 +76,30 @@ where
opts
}
Err(err) => {
match err.downcast_ref::<Error>() {
let hint = match err.downcast_ref::<Error>() {
Some(Error::Help) => {
term::help(help.name, help.version, help.description, help.usage);
process::exit(0);
}
Some(Error::HelpManual) => {
let Ok(status) = term::manual(help.name) else {
perror(help.name, "failed to load manual page");
process::exit(1);
};
process::exit(status.code().unwrap_or(0));
}
Some(Error::Usage) => {
term::usage(help.name, help.usage);
process::exit(1);
}
_ => {}
Some(Error::WithHint { hint, .. }) => Some(hint),
None => None,
};
eprintln!(
"{} {} rad {}: {err}",
Paint::red(ERROR_PREFIX),
Paint::red("Error:"),
help.name,
);
perror(help.name, &err);
if let Some(Error::WithHint { hint, .. }) = err.downcast_ref::<Error>() {
if let Some(hint) = hint {
eprintln!("{}", Paint::yellow(hint));
}
process::exit(1);
}
};
@ -123,6 +125,15 @@ pub fn profile() -> Result<Profile, anyhow::Error> {
}
}
pub fn perror(name: &str, err: impl std::fmt::Display) {
eprintln!(
"{} {} rad {}: {err}",
Paint::red(ERROR_PREFIX),
Paint::red("Error:"),
name,
);
}
pub fn fail(header: &str, error: &anyhow::Error) {
let err = error.to_string();
let err = err.trim_end();

View File

@ -15,6 +15,9 @@ pub enum Error {
/// If this error is returned from argument parsing, help is displayed.
#[error("help invoked")]
Help,
/// If this error is returned from argument parsing, the manual page is displayed.
#[error("help manual invoked")]
HelpManual,
/// If this error is returned from argument parsing, usage is displayed.
#[error("usage invoked")]
Usage,

View File

@ -1,5 +1,5 @@
use std::ffi::OsStr;
use std::{env, fmt};
use std::{env, fmt, io, process};
use inquire::ui::{ErrorMessageRenderConfig, StyleSheet, Styled};
use inquire::InquireError;
@ -123,6 +123,14 @@ pub fn help(name: &str, version: &str, description: &str, usage: &str) {
println!("rad-{name} {version}\n{description}\n{usage}");
}
pub fn manual(name: &str) -> io::Result<process::ExitStatus> {
let mut child = process::Command::new("man")
.arg(format!("rad-{name}"))
.spawn()?;
child.wait()
}
pub fn usage(name: &str, usage: &str) {
println!(
"{} {}\n{}",