radicle_cli/commands/
help.rs

1use std::ffi::OsString;
2
3use crate::terminal as term;
4use crate::terminal::args::{Args, Error, Help};
5
6pub const HELP: Help = Help {
7    name: "help",
8    description: "CLI help",
9    version: env!("RADICLE_VERSION"),
10    usage: "Usage: rad help [--help]",
11};
12
13enum CommandItem {
14    Lexopt(Help),
15    Clap {
16        name: &'static str,
17        about: &'static str,
18    },
19}
20
21impl CommandItem {
22    fn name(&self) -> &str {
23        match self {
24            CommandItem::Lexopt(help) => help.name,
25            CommandItem::Clap { name, .. } => name,
26        }
27    }
28
29    fn description(&self) -> &str {
30        match self {
31            CommandItem::Lexopt(help) => help.description,
32            CommandItem::Clap {
33                about: description, ..
34            } => description,
35        }
36    }
37}
38
39const COMMANDS: &[CommandItem] = &[
40    CommandItem::Lexopt(crate::commands::auth::HELP),
41    CommandItem::Lexopt(crate::commands::block::HELP),
42    CommandItem::Lexopt(crate::commands::checkout::HELP),
43    CommandItem::Lexopt(crate::commands::clone::HELP),
44    CommandItem::Lexopt(crate::commands::config::HELP),
45    CommandItem::Lexopt(crate::commands::fork::HELP),
46    CommandItem::Lexopt(crate::commands::help::HELP),
47    CommandItem::Lexopt(crate::commands::id::HELP),
48    CommandItem::Lexopt(crate::commands::init::HELP),
49    CommandItem::Lexopt(crate::commands::inbox::HELP),
50    CommandItem::Lexopt(crate::commands::inspect::HELP),
51    CommandItem::Clap {
52        name: "issue",
53        about: crate::commands::issue::ABOUT,
54    },
55    CommandItem::Lexopt(crate::commands::ls::HELP),
56    CommandItem::Lexopt(crate::commands::node::HELP),
57    CommandItem::Lexopt(crate::commands::patch::HELP),
58    CommandItem::Clap {
59        name: "path",
60        about: crate::commands::path::ABOUT,
61    },
62    CommandItem::Clap {
63        name: "clean",
64        about: crate::commands::clean::ABOUT,
65    },
66    CommandItem::Lexopt(crate::commands::rad_self::HELP),
67    CommandItem::Lexopt(crate::commands::seed::HELP),
68    CommandItem::Lexopt(crate::commands::follow::HELP),
69    CommandItem::Lexopt(crate::commands::unblock::HELP),
70    CommandItem::Clap {
71        name: "unfollow",
72        about: crate::commands::unfollow::ABOUT,
73    },
74    CommandItem::Clap {
75        name: "unseed",
76        about: crate::commands::unseed::ABOUT,
77    },
78    CommandItem::Lexopt(crate::commands::remote::HELP),
79    CommandItem::Clap {
80        name: "stats",
81        about: crate::commands::stats::ABOUT,
82    },
83    CommandItem::Lexopt(crate::commands::sync::HELP),
84];
85
86#[derive(Default)]
87pub struct Options {}
88
89impl Args for Options {
90    fn from_args(args: Vec<OsString>) -> anyhow::Result<(Self, Vec<OsString>)> {
91        let mut parser = lexopt::Parser::from_args(args);
92
93        if let Some(arg) = parser.next()? {
94            anyhow::bail!(arg.unexpected());
95        }
96        Err(Error::HelpManual { name: "rad" }.into())
97    }
98}
99
100pub fn run(_options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
101    term::print("Usage: rad <command> [--help]");
102
103    if let Err(e) = ctx.profile() {
104        term::blank();
105        match e.downcast_ref() {
106            Some(term::args::Error::WithHint { err, hint }) => {
107                term::print(term::format::yellow(err));
108                term::print(term::format::yellow(hint));
109            }
110            Some(e) => {
111                term::error(e);
112            }
113            None => {
114                term::error(e);
115            }
116        }
117        term::blank();
118    }
119
120    term::print("Common `rad` commands used in various situations:");
121    term::blank();
122
123    for help in COMMANDS {
124        term::info!(
125            "\t{} {}",
126            term::format::bold(format!("{:-12}", help.name())),
127            term::format::dim(help.description())
128        );
129    }
130    term::blank();
131    term::print("See `rad <command> --help` to learn about a specific command.");
132    term::blank();
133
134    term::print("Do you have feedback?");
135    term::print(
136        " - Chat <\x1b]8;;https://radicle.zulipchat.com\x1b\\radicle.zulipchat.com\x1b]8;;\x1b\\>",
137    );
138    term::print(
139        " - Mail <\x1b]8;;mailto:feedback@radicle.xyz\x1b\\feedback@radicle.xyz\x1b]8;;\x1b\\>",
140    );
141    term::print("   (Messages are automatically posted to the public #feedback channel on Zulip.)");
142
143    Ok(())
144}