Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for argument aliases in options and subcommands #1

Open
wants to merge 1 commit into
base: fix/clippy
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions docs/examples/complex-app-custom.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ An example command-line tool

###### **Subcommands:**

* `test` — does testing things
* `test` [alias: `tester`] — does testing things
* `only-hidden-options` — Demo that `Options` is not printed if all options are hidden

###### **Arguments:**
Expand All @@ -21,7 +21,7 @@ An example command-line tool

###### **Options:**

* `-c`, `--config <FILE>` — Sets a custom config file
* `-c`, `--config <FILE>` [alias: `configuration`] — Sets a custom config file
* `--target <TARGET>`

Default value: `local`
Expand All @@ -31,13 +31,14 @@ An example command-line tool
Do the operation locally
- `remote`

* `--very-very-verbose` [aliases: `vv`, `vvv`]
* `-d`, `--debug` — Turn debugging information on

Repeat this option to see more and more debug information.



## `complex-app test`
## `complex-app test` [alias: `tester`]

does testing things

Expand Down
7 changes: 4 additions & 3 deletions docs/examples/complex-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ An example command-line tool

###### **Subcommands:**

* `test` — does testing things
* `test` [alias: `tester`] — does testing things
* `only-hidden-options` — Demo that `Options` is not printed if all options are hidden

###### **Arguments:**
Expand All @@ -27,7 +27,7 @@ An example command-line tool

###### **Options:**

* `-c`, `--config <FILE>` — Sets a custom config file
* `-c`, `--config <FILE>` [alias: `configuration`] — Sets a custom config file
* `--target <TARGET>`

Default value: `local`
Expand All @@ -37,13 +37,14 @@ An example command-line tool
Do the operation locally
- `remote`

* `--very-very-verbose` [aliases: `vv`, `vvv`]
* `-d`, `--debug` — Turn debugging information on

Repeat this option to see more and more debug information.



## `complex-app test`
## `complex-app test` [alias: `tester`]

does testing things

Expand Down
6 changes: 5 additions & 1 deletion docs/examples/complex_app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@ pub struct Cli {
name: Option<String>,

/// Sets a custom config file
#[arg(short, long, value_name = "FILE")]
#[arg(short, long, value_name = "FILE", visible_alias = "configuration")]
config: Option<PathBuf>,

#[arg(long, default_value = "local")]
target: Target,

#[arg(long, visible_alias = "vv", visible_alias = "vvv")]
very_very_verbose: bool,

/// Turn debugging information on
///
/// Repeat this option to see more and more debug information.
Expand All @@ -34,6 +37,7 @@ pub struct Cli {
#[derive(Subcommand)]
enum Commands {
/// does testing things
#[command(visible_alias = "tester")]
Test {
/// lists test values
#[arg(short, long)]
Expand Down
55 changes: 47 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,12 +309,12 @@ fn build_command_markdown(
)
}
*/
let aliases = command.get_visible_aliases().collect::<Vec<&str>>();
let aliases = get_alias_str(&aliases)
.map(|s| format!(" {s}"))
.unwrap_or_default();

writeln!(
buffer,
"## `{}`\n",
command_path.join(" "),
)?;
writeln!(buffer, "## `{}`{aliases}\n", command_path.join(" "),)?;

if let Some(long_about) = command.get_long_about() {
writeln!(buffer, "{}\n", long_about)?;
Expand Down Expand Up @@ -364,13 +364,17 @@ fn build_command_markdown(
}

let title_name = get_canonical_name(subcommand);
let aliases = subcommand.get_visible_aliases().collect::<Vec<&str>>();
let aliases = get_alias_str(&aliases)
.map(|s| format!(" {s}"))
.unwrap_or_default();

let about = match subcommand.get_about() {
Some(about) => about.to_string(),
None => String::new(),
};

writeln!(buffer, "* `{title_name}` — {about}",)?;
writeln!(buffer, "* `{title_name}`{aliases} — {about}",)?;
}

writeln!(buffer)?;
Expand Down Expand Up @@ -459,9 +463,9 @@ fn write_arg_markdown(buffer: &mut String, arg: &clap::Arg) -> fmt::Result {
},
(None, Some(long)) => {
if arg.get_action().takes_values() {
write!(buffer, "`--{} <{value_name}>`", long)?
write!(buffer, "`--{long} <{value_name}>`")?
} else {
write!(buffer, "`--{}`", long)?
write!(buffer, "`--{long}`")?
}
},
(None, None) => {
Expand All @@ -471,6 +475,12 @@ fn write_arg_markdown(buffer: &mut String, arg: &clap::Arg) -> fmt::Result {
},
}

if let Some(aliases) = arg.get_visible_aliases().as_deref() {
if let Some(aliases) = get_alias_str(aliases) {
write!(buffer, " {aliases}")?;
}
}

if let Some(help) = arg.get_long_help() {
// TODO: Parse formatting in the string
buffer.push_str(&indent(&help.to_string(), " — ", " "))
Expand Down Expand Up @@ -597,6 +607,35 @@ fn indent(s: &str, first: &str, rest: &str) -> String {
result
}

fn wrap_with(s: &str, wrapper: &str) -> String {
format!("{wrapper}{s}{wrapper}")
}

fn wrap_with_backticks(s: &str) -> String {
wrap_with(s, "`")
}

fn get_alias_str(aliases: &[&str]) -> Option<String> {
if aliases.is_empty() {
return None;
}

let prefix = if aliases.len() == 1 {
"alias"
} else {
"aliases"
};

Some(format!(
"[{prefix}: {}]",
aliases
.iter()
.map(|s| wrap_with_backticks(s))
.collect::<Vec<_>>()
.join(", ")
))
}

#[cfg(test)]
mod test {
use pretty_assertions::assert_eq;
Expand Down