Skip to content
Merged
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
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ rust-version = "1.86"
anyhow = { workspace = true }
async-trait = { workspace = true }
bytes = { workspace = true }
clap = { workspace = true, features = ["derive", "env"] }
# 'deprecated' enables deprecation warnings
clap = { workspace = true, features = ["deprecated", "derive", "env"] }
clearscreen = "4"
comfy-table = "7"
command-group = "2"
Expand Down
4 changes: 2 additions & 2 deletions crates/runtime-factors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ pub struct TriggerAppArgs {
/// Set a key/value pair (key=value) in the application's
/// default store. Any existing value will be overwritten.
/// Can be used multiple times.
#[clap(long = "key-value", parse(try_from_str = parse_kv))]
#[clap(long = "key-value", value_parser = parse_kv)]
pub key_values: Vec<(String, String)>,

/// Run a SQLite statement such as a migration against the default database.
Expand All @@ -116,7 +116,7 @@ pub struct TriggerAppArgs {
///
/// This option may be repeated. If the same key is specified multiple times
/// the last value will be used.
#[clap(long, multiple = true, value_parser = clap::value_parser!(VariableSource),
#[clap(long, value_parser = clap::value_parser!(VariableSource),
value_name = "KEY=VALUE | @FILE.json | @FILE.toml")]
pub variable: Vec<VariableSource>,

Expand Down
3 changes: 1 addition & 2 deletions crates/trigger/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub const SPIN_WORKING_DIR: &str = "SPIN_WORKING_DIR";
/// A command that runs a TriggerExecutor.
#[derive(Parser, Debug)]
#[clap(
usage = "spin [COMMAND] [OPTIONS]",
override_usage = "spin [COMMAND] [OPTIONS]",
next_help_heading = help_heading::<T, B::Factors>()
)]
pub struct FactorsTriggerCommand<T: Trigger<B::Factors>, B: RuntimeFactorsBuilder> {
Expand Down Expand Up @@ -89,7 +89,6 @@ pub struct FactorsTriggerCommand<T: Trigger<B::Factors>, B: RuntimeFactorsBuilde
#[clap(
name = FOLLOW_LOG_OPT,
long = "follow",
multiple_occurrences = true,
)]
pub follow_components: Vec<String>,

Expand Down
76 changes: 30 additions & 46 deletions src/clap_markdown/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! the upstream crate because it is Clap 4 only. When we move to Clap 4
//! we should shift to using the original crate (and upstream changes such
//! as alphabetisation). See licences in this directory and NOTICES.md.
//!
//!
//! Autogenerate Markdown documentation for clap command-line tools
//!
//! See [**Examples**][Examples] for examples of the content `clap-markdown`
Expand Down Expand Up @@ -79,9 +79,7 @@ pub fn help_markdown<C: clap::CommandFactory>() -> String {
}

/// Format the help information for `command` as Markdown, with custom options.
pub fn help_markdown_custom<C: clap::CommandFactory>(
options: &MarkdownOptions,
) -> String {
pub fn help_markdown_custom<C: clap::CommandFactory>(options: &MarkdownOptions) -> String {
let command = C::command();

return help_markdown_command_custom(&command, options);
Expand All @@ -93,10 +91,7 @@ pub fn help_markdown_command(command: &clap::Command) -> String {
}

/// Format the help information for `command` as Markdown, with custom options.
pub fn help_markdown_command_custom(
command: &clap::Command,
options: &MarkdownOptions,
) -> String {
pub fn help_markdown_command_custom(command: &clap::Command, options: &MarkdownOptions) -> String {
let mut buffer = String::with_capacity(100);

write_help_markdown(&mut buffer, &command, options);
Expand All @@ -121,11 +116,7 @@ pub fn print_help_markdown<C: clap::CommandFactory>() {
println!("{}", buffer);
}

fn write_help_markdown(
buffer: &mut String,
command: &clap::Command,
options: &MarkdownOptions,
) {
fn write_help_markdown(buffer: &mut String, command: &clap::Command, options: &MarkdownOptions) {
//----------------------------------
// Write the document title
//----------------------------------
Expand All @@ -142,7 +133,8 @@ fn write_help_markdown(
buffer,
"This document contains the help content for the `{}` command-line program.\n",
title_name
).unwrap();
)
.unwrap();

//----------------------------------
// Write the table of contents
Expand All @@ -155,8 +147,7 @@ fn write_help_markdown(
if options.show_table_of_contents {
writeln!(buffer, "**Command Overview:**\n").unwrap();

build_table_of_contents_markdown(buffer, Vec::new(), command, 0)
.unwrap();
build_table_of_contents_markdown(buffer, Vec::new(), command, 0).unwrap();

write!(buffer, "\n").unwrap();
}
Expand All @@ -171,13 +162,17 @@ fn write_help_markdown(
// Write the footer
//-----------------
if options.show_footer {
write!(buffer, r#"<hr/>
write!(
buffer,
r#"<hr/>

<small><i>
This document was generated automatically by
<a href="https://crates.io/crates/clap-markdown"><code>clap-markdown</code></a>.
</i></small>
"#).unwrap();
"#
)
.unwrap();
}
}

Expand Down Expand Up @@ -215,12 +210,7 @@ fn build_table_of_contents_markdown(
//----------------------------------

for subcommand in command.get_subcommands().sorted_by_key(|c| c.get_name()) {
build_table_of_contents_markdown(
buffer,
command_path.clone(),
subcommand,
depth + 1,
)?;
build_table_of_contents_markdown(buffer, command_path.clone(), subcommand, depth + 1)?;
}

Ok(())
Expand Down Expand Up @@ -418,12 +408,7 @@ fn build_command_markdown(
write!(buffer, "\n\n")?;

for subcommand in command.get_subcommands().sorted_by_key(|c| c.get_name()) {
build_command_markdown(
buffer,
command_path.clone(),
subcommand,
depth + 1,
)?;
build_command_markdown(buffer, command_path.clone(), subcommand, depth + 1)?;
}

Ok(())
Expand All @@ -447,9 +432,7 @@ fn write_arg_markdown(buffer: &mut String, arg: &clap::Arg) -> fmt::Result {
let value_name: String = match arg.get_value_names() {
// TODO: What if multiple names are provided?
Some([name, ..]) => name.to_string(),
Some([]) => unreachable!(
"clap Arg::get_value_names() returned Some(..) of empty list"
),
Some([]) => unreachable!("clap Arg::get_value_names() returned Some(..) of empty list"),
None => arg.get_id().to_string().to_ascii_uppercase(),
};

Expand All @@ -460,26 +443,29 @@ fn write_arg_markdown(buffer: &mut String, arg: &clap::Arg) -> fmt::Result {
} else {
write!(buffer, "`-{short}`, `--{long}`")?
}
},
}
(Some(short), None) => {
if arg.get_action().takes_values() {
write!(buffer, "`-{short} <{value_name}>`")?
} else {
write!(buffer, "`-{short}`")?
}
},
}
(None, Some(long)) => {
if arg.get_action().takes_values() {
write!(buffer, "`--{} <{value_name}>`", long)?
} else {
write!(buffer, "`--{}`", long)?
}
},
}
(None, None) => {
debug_assert!(arg.is_positional(), "unexpected non-positional Arg with neither short nor long name: {arg:?}");
debug_assert!(
arg.is_positional(),
"unexpected non-positional Arg with neither short nor long name: {arg:?}"
);

write!(buffer, "`<{value_name}>`",)?;
},
}
}

if let Some(help) = arg.get_long_help() {
Expand Down Expand Up @@ -517,19 +503,17 @@ fn write_arg_markdown(buffer: &mut String, arg: &clap::Arg) -> fmt::Result {
//--------------------

let possible_values = arg
.get_possible_values()
.unwrap_or_default()
.get_value_parser()
.possible_values()
.into_iter()
.flatten()
Comment on lines -520 to +509
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was the only substantive change in this file. The rest was rustfmt.

.filter(|pv| !pv.is_hide_set())
.collect::<Vec<_>>();

// Print possible values for options that take a value, but not for flags
// that can only be either present or absent and do not take a value.
if !possible_values.is_empty()
&& !matches!(arg.get_action(), clap::ArgAction::SetTrue)
{
let any_have_help: bool =
possible_values.iter().any(|pv| pv.get_help().is_some());
if !possible_values.is_empty() && !matches!(arg.get_action(), clap::ArgAction::SetTrue) {
let any_have_help: bool = possible_values.iter().any(|pv| pv.get_help().is_some());

if any_have_help {
// If any of the possible values have help text, print them
Expand All @@ -548,7 +532,7 @@ fn write_arg_markdown(buffer: &mut String, arg: &clap::Arg) -> fmt::Result {
.map(|pv| match pv.get_help() {
Some(help) => {
format!(" - `{}`:\n {}\n", pv.get_name(), help)
},
}
None => format!(" - `{}`\n", pv.get_name()),
})
.collect::<Vec<String>>()
Expand Down
2 changes: 1 addition & 1 deletion src/commands/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub struct BuildCommand {
pub app_source: Option<PathBuf>,

/// Component ID to build. This can be specified multiple times. The default is all components.
#[clap(short = 'c', long, multiple = true)]
#[clap(short = 'c', long)]
pub component_id: Vec<String>,

/// Run the application after building.
Expand Down
24 changes: 12 additions & 12 deletions src/commands/cloud.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,24 +35,24 @@ const DEFAULT_DEPLOY_PLUGIN: &str = "cloud";
const DEPLOY_PLUGIN_ENV: &str = "SPIN_DEPLOY_PLUGIN";

impl DeployCommand {
pub async fn run(self, app: clap::App<'_>) -> Result<()> {
const CMD: &str = "deploy";
pub async fn run(self, cmd: clap::Command<'_>) -> Result<()> {
const SUBCMD: &str = "deploy";

let deploy_plugin = deployment_plugin(CMD)?;
let mut cmd = vec![deploy_plugin, CMD.to_string()];
cmd.append(&mut self.args.clone());
execute_external_subcommand(cmd, app).await
let deploy_plugin = deployment_plugin(SUBCMD)?;
let mut subcmd = vec![deploy_plugin, SUBCMD.to_string()];
subcmd.append(&mut self.args.clone());
execute_external_subcommand(subcmd, cmd).await
}
}

impl LoginCommand {
pub async fn run(self, app: clap::App<'_>) -> Result<()> {
const CMD: &str = "login";
pub async fn run(self, cmd: clap::Command<'_>) -> Result<()> {
const SUBCMD: &str = "login";

let deploy_plugin = deployment_plugin(CMD)?;
let mut cmd = vec![deploy_plugin, CMD.to_string()];
cmd.append(&mut self.args.clone());
execute_external_subcommand(cmd, app).await
let deploy_plugin = deployment_plugin(SUBCMD)?;
let mut subcmd = vec![deploy_plugin, SUBCMD.to_string()];
subcmd.append(&mut self.args.clone());
execute_external_subcommand(subcmd, cmd).await
}
}

Expand Down
24 changes: 12 additions & 12 deletions src/commands/external.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,15 @@ pub fn predefined_externals() -> Vec<(String, String)> {
/// indicate the plugin to execute. Passes all subsequent arguments on to the
/// subprocess.
pub async fn execute_external_subcommand(
cmd: Vec<String>,
app: clap::App<'_>,
subcmd: Vec<String>,
cmd: clap::Command<'_>,
) -> anyhow::Result<()> {
let (plugin_name, args, override_compatibility_check) = parse_subcommand(cmd)?;
let (plugin_name, args, override_compatibility_check) = parse_subcommand(subcmd)?;
let plugin_store = PluginStore::try_default()?;
let plugin_version = ensure_plugin_available(
&plugin_name,
&plugin_store,
app,
cmd,
override_compatibility_check,
)
.await?;
Expand Down Expand Up @@ -115,7 +115,7 @@ fn set_kill_on_ctrl_c(child: &tokio::process::Child) {
async fn ensure_plugin_available(
plugin_name: &str,
plugin_store: &PluginStore,
app: clap::App<'_>,
cmd: clap::Command<'_>,
override_compatibility_check: bool,
) -> anyhow::Result<Option<String>> {
let plugin_version = match plugin_store.read_plugin_manifest(plugin_name) {
Expand All @@ -130,7 +130,7 @@ async fn ensure_plugin_available(
Some(manifest.version().to_owned())
}
Err(PluginError::NotFound(e)) => {
consider_install(plugin_name, plugin_store, app, &e).await?
consider_install(plugin_name, plugin_store, cmd, &e).await?
}
Err(e) => return Err(e.into()),
};
Expand All @@ -140,7 +140,7 @@ async fn ensure_plugin_available(
async fn consider_install(
plugin_name: &str,
plugin_store: &PluginStore,
app: clap::App<'_>,
cmd: clap::Command<'_>,
e: &spin_plugins::error::NotFoundError,
) -> anyhow::Result<Option<String>> {
if predefined_externals()
Expand Down Expand Up @@ -176,7 +176,7 @@ async fn consider_install(

tracing::debug!("Tried to resolve {plugin_name} to plugin, got {e}");
terminal::error!("'{plugin_name}' is not a known Spin command. See spin --help.\n");
print_similar_commands(app, plugin_name);
print_similar_commands(cmd, plugin_name);
process::exit(2);
}

Expand Down Expand Up @@ -280,8 +280,8 @@ async fn report_badger_result(badger: tokio::task::JoinHandle<BadgerChecker>) {
}
}

fn print_similar_commands(app: clap::App, plugin_name: &str) {
let similar = similar_commands(app, plugin_name);
fn print_similar_commands(cmd: clap::Command, plugin_name: &str) {
let similar = similar_commands(cmd, plugin_name);
match similar.len() {
0 => (),
1 => eprintln!("The most similar command is:"),
Expand All @@ -295,8 +295,8 @@ fn print_similar_commands(app: clap::App, plugin_name: &str) {
}
}

fn similar_commands(app: clap::App, target: &str) -> Vec<String> {
app.get_subcommands()
fn similar_commands(cmd: clap::Command, target: &str) -> Vec<String> {
cmd.get_subcommands()
.filter_map(|sc| {
let actual_name = undecorate(sc.get_name());
if levenshtein::levenshtein(&actual_name, target) <= 2 {
Expand Down
8 changes: 2 additions & 6 deletions src/commands/new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,7 @@ pub struct TemplateNewCommandCore {
pub template_id: Option<String>,

/// Filter templates to select by tags.
#[clap(
long = "tag",
multiple_occurrences = true,
conflicts_with = "template-id"
)]
#[clap(long = "tag", conflicts_with = "template-id")]
pub tags: Vec<String>,

/// The directory in which to create the new application or component.
Expand All @@ -50,7 +46,7 @@ pub struct TemplateNewCommandCore {
pub init: bool,

/// Parameter values to be passed to the template (in name=value format).
#[clap(short = 'v', long = "value", multiple_occurrences = true)]
#[clap(short = 'v', long = "value")]
pub values: Vec<ParameterValue>,

/// A TOML file which contains parameter values in name = "value" format.
Expand Down
2 changes: 1 addition & 1 deletion src/commands/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ pub struct Push {

/// Specifies the OCI image manifest annotations (in key=value format).
/// Any existing value will be overwritten. Can be used multiple times.
#[clap(long = "annotation", parse(try_from_str = parse_kv))]
#[clap(long = "annotation", value_parser = parse_kv)]
pub annotations: Vec<(String, String)>,
}

Expand Down
Loading
Loading