radicle_cli/commands/
help.rs1use 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}