mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 06:42:33 +00:00
refactor: refactor generate_completion
This commit is contained in:
parent
54a12e8178
commit
f1bc5a554a
1 changed files with 105 additions and 43 deletions
148
src/lib.rs
148
src/lib.rs
|
@ -1,11 +1,106 @@
|
||||||
//! Generates [Nushell](https://github.com/nushell/nushell) completions for [`clap`](https://github.com/clap-rs/clap) based CLIs
|
//! Generates [Nushell](https://github.com/nushell/nushell) completions for [`clap`](https://github.com/clap-rs/clap) based CLIs
|
||||||
|
|
||||||
use clap::Command;
|
use clap::{Arg, Command};
|
||||||
use clap_complete::Generator;
|
use clap_complete::Generator;
|
||||||
|
|
||||||
/// Generate Nushell complete file
|
/// Generate Nushell complete file
|
||||||
pub struct Nushell;
|
pub struct Nushell;
|
||||||
|
|
||||||
|
enum Argument {
|
||||||
|
Short(char),
|
||||||
|
Long(String),
|
||||||
|
ShortAndLong(char, String),
|
||||||
|
Positional(String, bool),
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ArgumentLine {
|
||||||
|
arg: Argument,
|
||||||
|
takes_values: bool,
|
||||||
|
help: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&Arg> for ArgumentLine {
|
||||||
|
fn from(arg: &Arg) -> Self {
|
||||||
|
let takes_values = arg
|
||||||
|
.get_num_args()
|
||||||
|
.map(|v| v.takes_values())
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
let help = arg.get_help().map(|s| s.to_string());
|
||||||
|
|
||||||
|
if arg.is_positional() {
|
||||||
|
let id = arg.get_id().to_string();
|
||||||
|
let required = arg.is_required_set();
|
||||||
|
let arg = Argument::Positional(id, required);
|
||||||
|
|
||||||
|
return Self {
|
||||||
|
arg,
|
||||||
|
takes_values,
|
||||||
|
help,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let short = arg.get_short();
|
||||||
|
let long = arg.get_long();
|
||||||
|
|
||||||
|
match short {
|
||||||
|
Some(short) => match long {
|
||||||
|
Some(long) => Self {
|
||||||
|
arg: Argument::ShortAndLong(short, long.into()),
|
||||||
|
takes_values,
|
||||||
|
help,
|
||||||
|
},
|
||||||
|
None => Self {
|
||||||
|
arg: Argument::Short(short),
|
||||||
|
takes_values,
|
||||||
|
help,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
None => match long {
|
||||||
|
Some(long) => Self {
|
||||||
|
arg: Argument::Long(long.into()),
|
||||||
|
takes_values,
|
||||||
|
help,
|
||||||
|
},
|
||||||
|
None => unreachable!("No short or long option found"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToString for ArgumentLine {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
let mut s = String::new();
|
||||||
|
|
||||||
|
match &self.arg {
|
||||||
|
Argument::Short(short) => s.push_str(format!(" -{}", short).as_str()),
|
||||||
|
Argument::Long(long) => s.push_str(format!(" --{}", long).as_str()),
|
||||||
|
Argument::ShortAndLong(short, long) => {
|
||||||
|
s.push_str(format!(" --{}(-{})", long, short).as_str())
|
||||||
|
}
|
||||||
|
Argument::Positional(positional, required) => {
|
||||||
|
s.push_str(format!(" {}", positional).as_str());
|
||||||
|
|
||||||
|
if !*required {
|
||||||
|
s.push('?');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.takes_values {
|
||||||
|
s.push_str(": string");
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(help) = &self.help {
|
||||||
|
s.push_str(format!("\t# {}", help).as_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
s.push('\n');
|
||||||
|
|
||||||
|
s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Generator for Nushell {
|
impl Generator for Nushell {
|
||||||
fn file_name(&self, name: &str) -> String {
|
fn file_name(&self, name: &str) -> String {
|
||||||
format!("{}.nu", name)
|
format!("{}.nu", name)
|
||||||
|
@ -37,51 +132,18 @@ fn generate_completion(completions: &mut String, cmd: &Command, is_subcommand: b
|
||||||
|
|
||||||
let bin_name = cmd.get_bin_name().expect("Failed to get bin name");
|
let bin_name = cmd.get_bin_name().expect("Failed to get bin name");
|
||||||
|
|
||||||
if is_subcommand {
|
let name = if is_subcommand {
|
||||||
completions.push_str(format!(" export extern \"{}\" [\n", bin_name).as_str());
|
format!(r#""{}""#, bin_name)
|
||||||
} else {
|
} else {
|
||||||
completions.push_str(format!(" export extern {} [\n", bin_name).as_str());
|
bin_name.into()
|
||||||
}
|
};
|
||||||
|
|
||||||
let mut s = String::new();
|
completions.push_str(format!(" export extern {} [\n", name).as_str());
|
||||||
for arg in cmd.get_arguments() {
|
|
||||||
if arg.is_positional() {
|
|
||||||
s.push_str(format!(" {}", arg.get_id()).as_str());
|
|
||||||
if !arg.is_required_set() {
|
|
||||||
s.push('?');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let long = arg.get_long();
|
let s: String = cmd
|
||||||
if let Some(opt) = long {
|
.get_arguments()
|
||||||
s.push_str(format!(" --{}", opt).as_str());
|
.map(|arg| ArgumentLine::from(arg).to_string())
|
||||||
}
|
.collect();
|
||||||
|
|
||||||
let short = arg.get_short();
|
|
||||||
if let Some(opt) = short {
|
|
||||||
if long.is_some() {
|
|
||||||
s.push_str(format!("(-{})", opt).as_str());
|
|
||||||
} else {
|
|
||||||
s.push_str(format!(" -{}", opt).as_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(v) = arg.get_num_args() {
|
|
||||||
if v.takes_values() {
|
|
||||||
// TODO: add more types?
|
|
||||||
// TODO: add possible values?
|
|
||||||
s.push_str(": string");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(msg) = arg.get_help() {
|
|
||||||
if arg.is_positional() || long.is_some() || short.is_some() {
|
|
||||||
s.push_str(format!("\t# {}", msg).as_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s.push('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
completions.push_str(&s);
|
completions.push_str(&s);
|
||||||
completions.push_str(" ]\n\n");
|
completions.push_str(" ]\n\n");
|
||||||
|
|
Loading…
Reference in a new issue