mirror of
https://github.com/clap-rs/clap
synced 2024-12-13 14:22:34 +00:00
Merge #2721
2721: feat(generate): Give `Shell` superpowers to simplify getting started r=pksunkara a=epage Co-authored-by: Ed Page <eopage@gmail.com>
This commit is contained in:
commit
74cbe0bf09
22 changed files with 255 additions and 174 deletions
|
@ -12,23 +12,12 @@
|
|||
//! . ./value_hints_derive.fish
|
||||
//! ./target/debug/examples/value_hints_derive --<TAB>
|
||||
//! ```
|
||||
use clap::{App, AppSettings, ArgEnum, IntoApp, Parser, ValueHint};
|
||||
use clap_generate::generators::{Bash, Elvish, Fish, PowerShell, Zsh};
|
||||
use clap_generate::{generate, Generator};
|
||||
use clap::{App, AppSettings, IntoApp, Parser, ValueHint};
|
||||
use clap_generate::{generate, Generator, Shell};
|
||||
use std::ffi::OsString;
|
||||
use std::io;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(ArgEnum, Debug, PartialEq, Clone)]
|
||||
enum GeneratorChoice {
|
||||
Bash,
|
||||
Elvish,
|
||||
Fish,
|
||||
#[clap(name = "powershell")]
|
||||
PowerShell,
|
||||
Zsh,
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
#[clap(
|
||||
name = "value_hints_derive",
|
||||
|
@ -38,7 +27,7 @@ enum GeneratorChoice {
|
|||
struct Opt {
|
||||
/// If provided, outputs the completion file for given shell
|
||||
#[clap(long = "generate", arg_enum)]
|
||||
generator: Option<GeneratorChoice>,
|
||||
generator: Option<Shell>,
|
||||
// Showcasing all possible ValueHints:
|
||||
#[clap(long, value_hint = ValueHint::Unknown)]
|
||||
unknown: Option<String>,
|
||||
|
@ -68,8 +57,8 @@ struct Opt {
|
|||
email: Option<String>,
|
||||
}
|
||||
|
||||
fn print_completions<G: Generator>(app: &mut App) {
|
||||
generate::<G, _>(app, app.get_name().to_string(), &mut io::stdout());
|
||||
fn print_completions<G: Generator>(gen: G, app: &mut App) {
|
||||
generate(gen, app, app.get_name().to_string(), &mut io::stdout());
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -78,13 +67,7 @@ fn main() {
|
|||
if let Some(generator) = opt.generator {
|
||||
let mut app = Opt::into_app();
|
||||
eprintln!("Generating completion file for {:?}...", generator);
|
||||
match generator {
|
||||
GeneratorChoice::Bash => print_completions::<Bash>(&mut app),
|
||||
GeneratorChoice::Elvish => print_completions::<Elvish>(&mut app),
|
||||
GeneratorChoice::Fish => print_completions::<Fish>(&mut app),
|
||||
GeneratorChoice::PowerShell => print_completions::<PowerShell>(&mut app),
|
||||
GeneratorChoice::Zsh => print_completions::<Zsh>(&mut app),
|
||||
}
|
||||
print_completions(generator, &mut app);
|
||||
} else {
|
||||
println!("{:#?}", opt);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ clap = { path = "../", version = "=3.0.0-beta.4" }
|
|||
[dev-dependencies]
|
||||
pretty_assertions = "0.7"
|
||||
version-sync = "0.9"
|
||||
itertools = "0.10"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
|
|
@ -7,5 +7,5 @@ fn main() {
|
|||
.subcommand(App::new("test").subcommand(App::new("config")))
|
||||
.subcommand(App::new("hello"));
|
||||
|
||||
generate::<Bash, _>(&mut app, "myapp", &mut io::stdout());
|
||||
generate(Bash, &mut app, "myapp", &mut io::stdout());
|
||||
}
|
||||
|
|
|
@ -13,21 +13,18 @@
|
|||
//! ./target/debug/examples/value_hints --<TAB>
|
||||
//! ```
|
||||
use clap::{App, AppSettings, Arg, ValueHint};
|
||||
use clap_generate::generators::{Bash, Elvish, Fish, PowerShell, Zsh};
|
||||
use clap_generate::{generate, Generator};
|
||||
use clap_generate::{generate, Generator, Shell};
|
||||
use std::io;
|
||||
|
||||
fn build_cli() -> App<'static> {
|
||||
App::new("value_hints")
|
||||
// AppSettings::TrailingVarArg is required to use ValueHint::CommandWithArguments
|
||||
.setting(AppSettings::TrailingVarArg)
|
||||
.arg(Arg::new("generator").long("generate").possible_values([
|
||||
"bash",
|
||||
"elvish",
|
||||
"fish",
|
||||
"powershell",
|
||||
"zsh",
|
||||
]))
|
||||
.arg(
|
||||
Arg::new("generator")
|
||||
.long("generate")
|
||||
.possible_values(Shell::arg_values()),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("unknown")
|
||||
.long("unknown")
|
||||
|
@ -95,23 +92,16 @@ fn build_cli() -> App<'static> {
|
|||
)
|
||||
}
|
||||
|
||||
fn print_completions<G: Generator>(app: &mut App) {
|
||||
generate::<G, _>(app, app.get_name().to_string(), &mut io::stdout());
|
||||
fn print_completions<G: Generator>(gen: G, app: &mut App) {
|
||||
generate(gen, app, app.get_name().to_string(), &mut io::stdout());
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let matches = build_cli().get_matches();
|
||||
|
||||
if let Some(generator) = matches.value_of("generator") {
|
||||
if let Ok(generator) = matches.value_of_t::<Shell>("generator") {
|
||||
let mut app = build_cli();
|
||||
eprintln!("Generating completion file for {}...", generator);
|
||||
match generator {
|
||||
"bash" => print_completions::<Bash>(&mut app),
|
||||
"elvish" => print_completions::<Elvish>(&mut app),
|
||||
"fish" => print_completions::<Fish>(&mut app),
|
||||
"powershell" => print_completions::<PowerShell>(&mut app),
|
||||
"zsh" => print_completions::<Zsh>(&mut app),
|
||||
_ => panic!("Unknown generator"),
|
||||
}
|
||||
print_completions(generator, &mut app);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,13 +21,13 @@ pub trait Generator {
|
|||
/// pub struct Fish;
|
||||
///
|
||||
/// impl Generator for Fish {
|
||||
/// # fn generate(app: &App, buf: &mut dyn Write) {}
|
||||
/// fn file_name(name: &str) -> String {
|
||||
/// # fn generate(&self, app: &App, buf: &mut dyn Write) {}
|
||||
/// fn file_name(&self, name: &str) -> String {
|
||||
/// format!("{}.fish", name)
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
fn file_name(name: &str) -> String;
|
||||
fn file_name(&self, name: &str) -> String;
|
||||
|
||||
/// Generates output out of [`clap::App`](App).
|
||||
///
|
||||
|
@ -44,24 +44,24 @@ pub trait Generator {
|
|||
/// pub struct ClapDebug;
|
||||
///
|
||||
/// impl Generator for ClapDebug {
|
||||
/// fn generate(app: &App, buf: &mut dyn Write) {
|
||||
/// fn generate(&self, app: &App, buf: &mut dyn Write) {
|
||||
/// write!(buf, "{}", app).unwrap();
|
||||
/// }
|
||||
/// # fn file_name(name: &str) -> String {
|
||||
/// # fn file_name(&self, name: &str) -> String {
|
||||
/// # name.into()
|
||||
/// # }
|
||||
/// }
|
||||
/// ```
|
||||
fn generate(app: &App, buf: &mut dyn Write);
|
||||
fn generate(&self, app: &App, buf: &mut dyn Write);
|
||||
|
||||
/// Gets all subcommands including child subcommands in the form of `("name", "bin_name")`.
|
||||
///
|
||||
/// Subcommand `rustup toolchain install` would be converted to
|
||||
/// `("install", "rustup toolchain install")`.
|
||||
fn all_subcommands(app: &App) -> Vec<(String, String)> {
|
||||
let mut subcmds: Vec<_> = Self::subcommands(app);
|
||||
fn all_subcommands(&self, app: &App) -> Vec<(String, String)> {
|
||||
let mut subcmds: Vec<_> = self.subcommands(app);
|
||||
|
||||
for sc_v in app.get_subcommands().map(|s| Self::all_subcommands(s)) {
|
||||
for sc_v in app.get_subcommands().map(|s| self.all_subcommands(s)) {
|
||||
subcmds.extend(sc_v);
|
||||
}
|
||||
|
||||
|
@ -72,6 +72,7 @@ pub trait Generator {
|
|||
///
|
||||
/// **NOTE:** `path` should not contain the root `bin_name`.
|
||||
fn find_subcommand_with_path<'help, 'app>(
|
||||
&self,
|
||||
p: &'app App<'help>,
|
||||
path: Vec<&str>,
|
||||
) -> &'app App<'help> {
|
||||
|
@ -88,7 +89,7 @@ pub trait Generator {
|
|||
///
|
||||
/// Subcommand `rustup toolchain install` would be converted to
|
||||
/// `("install", "rustup toolchain install")`.
|
||||
fn subcommands(p: &App) -> Vec<(String, String)> {
|
||||
fn subcommands(&self, p: &App) -> Vec<(String, String)> {
|
||||
debug!("subcommands: name={}", p.get_name());
|
||||
debug!("subcommands: Has subcommands...{:?}", p.has_subcommands());
|
||||
|
||||
|
@ -115,7 +116,7 @@ pub trait Generator {
|
|||
|
||||
/// Gets all the short options, their visible aliases and flags of a [`clap::App`].
|
||||
/// Includes `h` and `V` depending on the [`clap::AppSettings`].
|
||||
fn shorts_and_visible_aliases(p: &App) -> Vec<char> {
|
||||
fn shorts_and_visible_aliases(&self, p: &App) -> Vec<char> {
|
||||
debug!("shorts: name={}", p.get_name());
|
||||
|
||||
p.get_arguments()
|
||||
|
@ -140,7 +141,7 @@ pub trait Generator {
|
|||
|
||||
/// Gets all the long options, their visible aliases and flags of a [`clap::App`].
|
||||
/// Includes `help` and `version` depending on the [`clap::AppSettings`].
|
||||
fn longs_and_visible_aliases(p: &App) -> Vec<String> {
|
||||
fn longs_and_visible_aliases(&self, p: &App) -> Vec<String> {
|
||||
debug!("longs: name={}", p.get_name());
|
||||
|
||||
p.get_arguments()
|
||||
|
@ -170,7 +171,7 @@ pub trait Generator {
|
|||
|
||||
/// Gets all the flags of a [`clap::App`](App).
|
||||
/// Includes `help` and `version` depending on the [`clap::AppSettings`].
|
||||
fn flags<'help>(p: &App<'help>) -> Vec<Arg<'help>> {
|
||||
fn flags<'help>(&self, p: &App<'help>) -> Vec<Arg<'help>> {
|
||||
debug!("flags: name={}", p.get_name());
|
||||
p.get_flags().cloned().collect()
|
||||
}
|
||||
|
@ -184,9 +185,9 @@ mod tests {
|
|||
struct Foo;
|
||||
|
||||
impl Generator for Foo {
|
||||
fn generate(_: &App, _: &mut dyn Write) {}
|
||||
fn generate(&self, _: &App, _: &mut dyn Write) {}
|
||||
|
||||
fn file_name(name: &str) -> String {
|
||||
fn file_name(&self, name: &str) -> String {
|
||||
name.to_string()
|
||||
}
|
||||
}
|
||||
|
@ -217,7 +218,7 @@ mod tests {
|
|||
let app = common();
|
||||
|
||||
assert_eq!(
|
||||
Foo::subcommands(&app),
|
||||
Foo.subcommands(&app),
|
||||
vec![
|
||||
("test".to_string(), "my-app test".to_string()),
|
||||
("hello".to_string(), "my-app hello".to_string()),
|
||||
|
@ -231,7 +232,7 @@ mod tests {
|
|||
let app = common();
|
||||
|
||||
assert_eq!(
|
||||
Foo::all_subcommands(&app),
|
||||
Foo.all_subcommands(&app),
|
||||
vec![
|
||||
("test".to_string(), "my-app test".to_string()),
|
||||
("hello".to_string(), "my-app hello".to_string()),
|
||||
|
@ -244,7 +245,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_find_subcommand_with_path() {
|
||||
let app = common();
|
||||
let sc_app = Foo::find_subcommand_with_path(&app, "test config".split(' ').collect());
|
||||
let sc_app = Foo.find_subcommand_with_path(&app, "test config".split(' ').collect());
|
||||
|
||||
assert_eq!(sc_app.get_name(), "config");
|
||||
}
|
||||
|
@ -252,13 +253,13 @@ mod tests {
|
|||
#[test]
|
||||
fn test_flags() {
|
||||
let app = common();
|
||||
let flags = Foo::flags(&app);
|
||||
let flags = Foo.flags(&app);
|
||||
|
||||
assert_eq!(flags.len(), 2);
|
||||
assert_eq!(flags[0].get_long(), Some("help"));
|
||||
assert_eq!(flags[1].get_long(), Some("version"));
|
||||
|
||||
let sc_flags = Foo::flags(Foo::find_subcommand_with_path(&app, vec!["test"]));
|
||||
let sc_flags = Foo.flags(Foo.find_subcommand_with_path(&app, vec!["test"]));
|
||||
|
||||
assert_eq!(sc_flags.len(), 3);
|
||||
assert_eq!(sc_flags[0].get_long(), Some("file"));
|
||||
|
@ -269,14 +270,14 @@ mod tests {
|
|||
#[test]
|
||||
fn test_shorts() {
|
||||
let app = common();
|
||||
let shorts = Foo::shorts_and_visible_aliases(&app);
|
||||
let shorts = Foo.shorts_and_visible_aliases(&app);
|
||||
|
||||
assert_eq!(shorts.len(), 2);
|
||||
assert_eq!(shorts[0], 'h');
|
||||
assert_eq!(shorts[1], 'V');
|
||||
|
||||
let sc_shorts =
|
||||
Foo::shorts_and_visible_aliases(Foo::find_subcommand_with_path(&app, vec!["test"]));
|
||||
Foo.shorts_and_visible_aliases(Foo.find_subcommand_with_path(&app, vec!["test"]));
|
||||
|
||||
assert_eq!(sc_shorts.len(), 4);
|
||||
assert_eq!(sc_shorts[0], 'p');
|
||||
|
@ -288,14 +289,14 @@ mod tests {
|
|||
#[test]
|
||||
fn test_longs() {
|
||||
let app = common();
|
||||
let longs = Foo::longs_and_visible_aliases(&app);
|
||||
let longs = Foo.longs_and_visible_aliases(&app);
|
||||
|
||||
assert_eq!(longs.len(), 2);
|
||||
assert_eq!(longs[0], "help");
|
||||
assert_eq!(longs[1], "version");
|
||||
|
||||
let sc_longs =
|
||||
Foo::longs_and_visible_aliases(Foo::find_subcommand_with_path(&app, vec!["test"]));
|
||||
Foo.longs_and_visible_aliases(Foo.find_subcommand_with_path(&app, vec!["test"]));
|
||||
|
||||
assert_eq!(sc_longs.len(), 4);
|
||||
assert_eq!(sc_longs[0], "path");
|
||||
|
|
|
@ -6,14 +6,15 @@ use crate::Generator;
|
|||
use clap::*;
|
||||
|
||||
/// Generate bash completion file
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Bash;
|
||||
|
||||
impl Generator for Bash {
|
||||
fn file_name(name: &str) -> String {
|
||||
fn file_name(&self, name: &str) -> String {
|
||||
format!("{}.bash", name)
|
||||
}
|
||||
|
||||
fn generate(app: &App, buf: &mut dyn Write) {
|
||||
fn generate(&self, app: &App, buf: &mut dyn Write) {
|
||||
let bin_name = app.get_bin_name().unwrap();
|
||||
|
||||
w!(
|
||||
|
@ -77,7 +78,8 @@ fn all_subcommands(app: &App) -> String {
|
|||
debug!("all_subcommands");
|
||||
|
||||
let mut subcmds = String::new();
|
||||
let mut scs = Bash::all_subcommands(app)
|
||||
let mut scs = Bash
|
||||
.all_subcommands(app)
|
||||
.iter()
|
||||
.map(|x| x.0.clone())
|
||||
.collect::<Vec<_>>();
|
||||
|
@ -104,7 +106,8 @@ fn subcommand_details(app: &App) -> String {
|
|||
debug!("subcommand_details");
|
||||
|
||||
let mut subcmd_dets = String::new();
|
||||
let mut scs = Bash::all_subcommands(app)
|
||||
let mut scs = Bash
|
||||
.all_subcommands(app)
|
||||
.iter()
|
||||
.map(|x| x.1.replace(" ", "__"))
|
||||
.collect::<Vec<_>>();
|
||||
|
@ -143,7 +146,7 @@ fn subcommand_details(app: &App) -> String {
|
|||
fn option_details_for_path(app: &App, path: &str) -> String {
|
||||
debug!("option_details_for_path: path={}", path);
|
||||
|
||||
let p = Bash::find_subcommand_with_path(app, path.split("__").skip(1).collect());
|
||||
let p = Bash.find_subcommand_with_path(app, path.split("__").skip(1).collect());
|
||||
let mut opts = String::new();
|
||||
|
||||
for o in p.get_opts() {
|
||||
|
@ -200,15 +203,17 @@ fn vals_for(o: &Arg) -> String {
|
|||
fn all_options_for_path(app: &App, path: &str) -> String {
|
||||
debug!("all_options_for_path: path={}", path);
|
||||
|
||||
let p = Bash::find_subcommand_with_path(app, path.split("__").skip(1).collect());
|
||||
let scs: Vec<_> = Bash::subcommands(p).iter().map(|x| x.0.clone()).collect();
|
||||
let p = Bash.find_subcommand_with_path(app, path.split("__").skip(1).collect());
|
||||
let scs: Vec<_> = Bash.subcommands(p).iter().map(|x| x.0.clone()).collect();
|
||||
|
||||
let opts = format!(
|
||||
"{shorts} {longs} {pos} {subcmds}",
|
||||
shorts = Bash::shorts_and_visible_aliases(p)
|
||||
shorts = Bash
|
||||
.shorts_and_visible_aliases(p)
|
||||
.iter()
|
||||
.fold(String::new(), |acc, s| format!("{} -{}", acc, s)),
|
||||
longs = Bash::longs_and_visible_aliases(p)
|
||||
longs = Bash
|
||||
.longs_and_visible_aliases(p)
|
||||
.iter()
|
||||
.fold(String::new(), |acc, l| format!("{} --{}", acc, l)),
|
||||
pos = p
|
||||
|
|
|
@ -7,14 +7,15 @@ use crate::INTERNAL_ERROR_MSG;
|
|||
use clap::*;
|
||||
|
||||
/// Generate elvish completion file
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Elvish;
|
||||
|
||||
impl Generator for Elvish {
|
||||
fn file_name(name: &str) -> String {
|
||||
fn file_name(&self, name: &str) -> String {
|
||||
format!("{}.elv", name)
|
||||
}
|
||||
|
||||
fn generate(app: &App, buf: &mut dyn Write) {
|
||||
fn generate(&self, app: &App, buf: &mut dyn Write) {
|
||||
let bin_name = app.get_bin_name().unwrap();
|
||||
|
||||
let mut names = vec![];
|
||||
|
@ -98,7 +99,7 @@ fn generate_inner<'help>(
|
|||
}
|
||||
}
|
||||
|
||||
for flag in Elvish::flags(p) {
|
||||
for flag in Elvish.flags(p) {
|
||||
if let Some(shorts) = flag.get_short_and_visible_aliases() {
|
||||
let tooltip = get_tooltip(flag.get_about(), shorts[0]);
|
||||
for short in shorts {
|
||||
|
|
|
@ -8,14 +8,15 @@ use clap::*;
|
|||
/// Generate fish completion file
|
||||
///
|
||||
/// Note: The fish generator currently only supports named options (-o/--option), not positional arguments.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Fish;
|
||||
|
||||
impl Generator for Fish {
|
||||
fn file_name(name: &str) -> String {
|
||||
fn file_name(&self, name: &str) -> String {
|
||||
format!("{}.fish", name)
|
||||
}
|
||||
|
||||
fn generate(app: &App, buf: &mut dyn Write) {
|
||||
fn generate(&self, app: &App, buf: &mut dyn Write) {
|
||||
let command = app.get_bin_name().unwrap();
|
||||
let mut buffer = String::new();
|
||||
|
||||
|
@ -95,7 +96,7 @@ fn gen_fish_inner(root_command: &str, parent_commands: &[&str], app: &App, buffe
|
|||
buffer.push('\n');
|
||||
}
|
||||
|
||||
for flag in Fish::flags(app) {
|
||||
for flag in Fish.flags(app) {
|
||||
let mut template = basic_template.clone();
|
||||
|
||||
if let Some(shorts) = flag.get_short_and_visible_aliases() {
|
||||
|
|
|
@ -7,14 +7,15 @@ use crate::INTERNAL_ERROR_MSG;
|
|||
use clap::*;
|
||||
|
||||
/// Generate powershell completion file
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct PowerShell;
|
||||
|
||||
impl Generator for PowerShell {
|
||||
fn file_name(name: &str) -> String {
|
||||
fn file_name(&self, name: &str) -> String {
|
||||
format!("_{}.ps1", name)
|
||||
}
|
||||
|
||||
fn generate(app: &App, buf: &mut dyn Write) {
|
||||
fn generate(&self, app: &App, buf: &mut dyn Write) {
|
||||
let bin_name = app.get_bin_name().unwrap();
|
||||
|
||||
let mut names = vec![];
|
||||
|
@ -114,7 +115,7 @@ fn generate_inner<'help>(
|
|||
}
|
||||
}
|
||||
|
||||
for flag in PowerShell::flags(p) {
|
||||
for flag in PowerShell.flags(p) {
|
||||
if let Some(shorts) = flag.get_short_and_visible_aliases() {
|
||||
let tooltip = get_tooltip(flag.get_about(), shorts[0]);
|
||||
for short in shorts {
|
||||
|
|
|
@ -7,14 +7,15 @@ use crate::INTERNAL_ERROR_MSG;
|
|||
use clap::*;
|
||||
|
||||
/// Generate zsh completion file
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Zsh;
|
||||
|
||||
impl Generator for Zsh {
|
||||
fn file_name(name: &str) -> String {
|
||||
fn file_name(&self, name: &str) -> String {
|
||||
format!("_{}", name)
|
||||
}
|
||||
|
||||
fn generate(app: &App, buf: &mut dyn Write) {
|
||||
fn generate(&self, app: &App, buf: &mut dyn Write) {
|
||||
w!(
|
||||
buf,
|
||||
format!(
|
||||
|
@ -101,7 +102,7 @@ _{bin_name_underscore}_commands() {{
|
|||
ret.push(parent_text);
|
||||
|
||||
// Next we start looping through all the children, grandchildren, etc.
|
||||
let mut all_subcommands = Zsh::all_subcommands(p);
|
||||
let mut all_subcommands = Zsh.all_subcommands(p);
|
||||
|
||||
all_subcommands.sort();
|
||||
all_subcommands.dedup();
|
||||
|
@ -217,7 +218,7 @@ fn get_subcommands_of(parent: &App) -> String {
|
|||
return String::new();
|
||||
}
|
||||
|
||||
let subcommand_names = Zsh::subcommands(parent);
|
||||
let subcommand_names = Zsh.subcommands(parent);
|
||||
let mut all_subcommands = vec![];
|
||||
|
||||
for &(ref name, ref bin_name) in &subcommand_names {
|
||||
|
@ -524,7 +525,7 @@ fn write_flags_of(p: &App, p_global: Option<&App>) -> String {
|
|||
|
||||
let mut ret = vec![];
|
||||
|
||||
for f in Zsh::flags(p) {
|
||||
for f in Zsh.flags(p) {
|
||||
debug!("write_flags_of:iter: f={}", f.get_name());
|
||||
|
||||
let help = f.get_about().map_or(String::new(), escape_help);
|
||||
|
|
|
@ -9,6 +9,44 @@
|
|||
//!
|
||||
//! - For generating at compile-time, see [`generate_to`]
|
||||
//! - For generating at runtime, see [`generate`]
|
||||
//!
|
||||
//! [`Shell`] is a convenience `enum` for an argument value type that implements `Generator`
|
||||
//! for each natively-supported shell type.
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! use clap::{App, AppSettings, Arg, ValueHint};
|
||||
//! use clap_generate::{generate, Generator, Shell};
|
||||
//! use std::io;
|
||||
//!
|
||||
//! fn build_cli() -> App<'static> {
|
||||
//! App::new("example")
|
||||
//! .arg(Arg::new("file")
|
||||
//! .about("some input file")
|
||||
//! .value_hint(ValueHint::AnyPath),
|
||||
//! )
|
||||
//! .arg(
|
||||
//! Arg::new("generator")
|
||||
//! .long("generate")
|
||||
//! .possible_values(Shell::arg_values()),
|
||||
//! )
|
||||
//! }
|
||||
//!
|
||||
//! fn print_completions<G: Generator>(gen: G, app: &mut App) {
|
||||
//! generate(gen, app, app.get_name().to_string(), &mut io::stdout());
|
||||
//! }
|
||||
//!
|
||||
//! fn main() {
|
||||
//! let matches = build_cli().get_matches();
|
||||
//!
|
||||
//! if let Ok(generator) = matches.value_of_t::<Shell>("generator") {
|
||||
//! let mut app = build_cli();
|
||||
//! eprintln!("Generating completion file for {}...", generator);
|
||||
//! print_completions(generator, &mut app);
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
#![doc(html_logo_url = "https://clap.rs/images/media/clap.png")]
|
||||
#![doc(html_root_url = "https://docs.rs/clap_generate/3.0.0-beta.4")]
|
||||
|
@ -118,7 +156,8 @@ pub use shell::Shell;
|
|||
/// };
|
||||
///
|
||||
/// let mut app = build_cli();
|
||||
/// let path = generate_to::<Bash, _, _>(
|
||||
/// let path = generate_to(
|
||||
/// Bash,
|
||||
/// &mut app, // We need to specify what generator to use
|
||||
/// "myapp", // We need to specify the bin name manually
|
||||
/// outdir, // We need to specify where to write to
|
||||
|
@ -136,7 +175,12 @@ pub use shell::Shell;
|
|||
///
|
||||
/// **NOTE:** Please look at the individual [generators]
|
||||
/// to see the name of the files generated.
|
||||
pub fn generate_to<G, S, T>(app: &mut clap::App, bin_name: S, out_dir: T) -> Result<PathBuf, Error>
|
||||
pub fn generate_to<G, S, T>(
|
||||
gen: G,
|
||||
app: &mut clap::App,
|
||||
bin_name: S,
|
||||
out_dir: T,
|
||||
) -> Result<PathBuf, Error>
|
||||
where
|
||||
G: Generator,
|
||||
S: Into<String>,
|
||||
|
@ -145,12 +189,12 @@ where
|
|||
app.set_bin_name(bin_name);
|
||||
|
||||
let out_dir = PathBuf::from(out_dir.into());
|
||||
let file_name = G::file_name(app.get_bin_name().unwrap());
|
||||
let file_name = gen.file_name(app.get_bin_name().unwrap());
|
||||
|
||||
let path = out_dir.join(file_name);
|
||||
let mut file = File::create(&path)?;
|
||||
|
||||
_generate::<G, S>(app, &mut file);
|
||||
_generate::<G, S>(gen, app, &mut file);
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
|
@ -176,7 +220,7 @@ where
|
|||
/// let matches = cli::build_cli().get_matches();
|
||||
///
|
||||
/// if matches.is_present("generate-bash-completions") {
|
||||
/// generate::<Bash, _>(&mut cli::build_cli(), "myapp", &mut io::stdout());
|
||||
/// generate(Bash, &mut cli::build_cli(), "myapp", &mut io::stdout());
|
||||
/// }
|
||||
///
|
||||
/// // normal logic continues...
|
||||
|
@ -189,16 +233,16 @@ where
|
|||
/// ```shell
|
||||
/// $ myapp generate-bash-completions > /usr/share/bash-completion/completions/myapp.bash
|
||||
/// ```
|
||||
pub fn generate<G, S>(app: &mut clap::App, bin_name: S, buf: &mut dyn Write)
|
||||
pub fn generate<G, S>(gen: G, app: &mut clap::App, bin_name: S, buf: &mut dyn Write)
|
||||
where
|
||||
G: Generator,
|
||||
S: Into<String>,
|
||||
{
|
||||
app.set_bin_name(bin_name);
|
||||
_generate::<G, S>(app, buf)
|
||||
_generate::<G, S>(gen, app, buf)
|
||||
}
|
||||
|
||||
fn _generate<G, S>(app: &mut clap::App, buf: &mut dyn Write)
|
||||
fn _generate<G, S>(gen: G, app: &mut clap::App, buf: &mut dyn Write)
|
||||
where
|
||||
G: Generator,
|
||||
S: Into<String>,
|
||||
|
@ -207,5 +251,5 @@ where
|
|||
app._build();
|
||||
app._build_bin_names();
|
||||
|
||||
G::generate(app, buf)
|
||||
gen.generate(app, buf)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use std::fmt::Display;
|
||||
use std::str::FromStr;
|
||||
|
||||
use clap::{ArgEnum, ArgValue};
|
||||
|
||||
/// Shell with auto-generated completion script available.
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
#[non_exhaustive]
|
||||
|
@ -18,21 +20,20 @@ pub enum Shell {
|
|||
}
|
||||
|
||||
impl Shell {
|
||||
/// A list of supported shells in `[&'static str]` form.
|
||||
pub fn variants() -> [&'static str; 5] {
|
||||
["bash", "elvish", "fish", "powershell", "zsh"]
|
||||
/// Report all `possible_values`
|
||||
pub fn arg_values() -> impl Iterator<Item = ArgValue<'static>> {
|
||||
Shell::value_variants()
|
||||
.iter()
|
||||
.filter_map(ArgEnum::to_arg_value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Shell {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match *self {
|
||||
Shell::Bash => write!(f, "bash"),
|
||||
Shell::Elvish => write!(f, "elvish"),
|
||||
Shell::Fish => write!(f, "fish"),
|
||||
Shell::PowerShell => write!(f, "powershell"),
|
||||
Shell::Zsh => write!(f, "zsh"),
|
||||
}
|
||||
self.to_arg_value()
|
||||
.expect("no values are skipped")
|
||||
.get_name()
|
||||
.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,15 +41,57 @@ impl FromStr for Shell {
|
|||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s.to_ascii_lowercase().as_str() {
|
||||
"bash" => Ok(Shell::Bash),
|
||||
"elvish" => Ok(Shell::Elvish),
|
||||
"fish" => Ok(Shell::Fish),
|
||||
"powershell" => Ok(Shell::PowerShell),
|
||||
"zsh" => Ok(Shell::Zsh),
|
||||
_ => Err(String::from(
|
||||
"[valid values: bash, elvish, fish, powershell, zsh]",
|
||||
)),
|
||||
for variant in Self::value_variants() {
|
||||
if variant.to_arg_value().unwrap().matches(s, false) {
|
||||
return Ok(*variant);
|
||||
}
|
||||
}
|
||||
Err(format!("Invalid variant: {}", s))
|
||||
}
|
||||
}
|
||||
|
||||
// Hand-rolled so it can work even when `derive` feature is disabled
|
||||
impl ArgEnum for Shell {
|
||||
fn value_variants<'a>() -> &'a [Self] {
|
||||
&[
|
||||
Shell::Bash,
|
||||
Shell::Elvish,
|
||||
Shell::Fish,
|
||||
Shell::PowerShell,
|
||||
Shell::Zsh,
|
||||
]
|
||||
}
|
||||
|
||||
fn to_arg_value<'a>(&self) -> Option<ArgValue<'a>> {
|
||||
let value = match self {
|
||||
Shell::Bash => ArgValue::new("bash"),
|
||||
Shell::Elvish => ArgValue::new("elvish"),
|
||||
Shell::Fish => ArgValue::new("fish"),
|
||||
Shell::PowerShell => ArgValue::new("powershell"),
|
||||
Shell::Zsh => ArgValue::new("zsh"),
|
||||
};
|
||||
Some(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::Generator for Shell {
|
||||
fn file_name(&self, name: &str) -> String {
|
||||
match self {
|
||||
Shell::Bash => crate::generators::Bash.file_name(name),
|
||||
Shell::Elvish => crate::generators::Elvish.file_name(name),
|
||||
Shell::Fish => crate::generators::Fish.file_name(name),
|
||||
Shell::PowerShell => crate::generators::PowerShell.file_name(name),
|
||||
Shell::Zsh => crate::generators::Zsh.file_name(name),
|
||||
}
|
||||
}
|
||||
|
||||
fn generate(&self, app: &clap::App, buf: &mut dyn std::io::Write) {
|
||||
match self {
|
||||
Shell::Bash => crate::generators::Bash.generate(app, buf),
|
||||
Shell::Elvish => crate::generators::Elvish.generate(app, buf),
|
||||
Shell::Fish => crate::generators::Fish.generate(app, buf),
|
||||
Shell::PowerShell => crate::generators::PowerShell.generate(app, buf),
|
||||
Shell::Zsh => crate::generators::Zsh.generate(app, buf),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ fn build_app_with_name(s: &'static str) -> App<'static> {
|
|||
#[test]
|
||||
fn bash() {
|
||||
let mut app = build_app();
|
||||
common::<Bash>(&mut app, "myapp", BASH);
|
||||
common(Bash, &mut app, "myapp", BASH);
|
||||
}
|
||||
|
||||
static BASH: &str = r#"_myapp() {
|
||||
|
@ -43,7 +43,7 @@ static BASH: &str = r#"_myapp() {
|
|||
myapp)
|
||||
cmd="myapp"
|
||||
;;
|
||||
|
||||
|
||||
help)
|
||||
cmd+="__help"
|
||||
;;
|
||||
|
@ -63,7 +63,7 @@ static BASH: &str = r#"_myapp() {
|
|||
return 0
|
||||
fi
|
||||
case "${prev}" in
|
||||
|
||||
|
||||
*)
|
||||
COMPREPLY=()
|
||||
;;
|
||||
|
@ -71,7 +71,7 @@ static BASH: &str = r#"_myapp() {
|
|||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
;;
|
||||
|
||||
|
||||
myapp__help)
|
||||
opts=" -h -V --help --version "
|
||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
|
||||
|
@ -79,7 +79,7 @@ static BASH: &str = r#"_myapp() {
|
|||
return 0
|
||||
fi
|
||||
case "${prev}" in
|
||||
|
||||
|
||||
*)
|
||||
COMPREPLY=()
|
||||
;;
|
||||
|
@ -94,7 +94,7 @@ static BASH: &str = r#"_myapp() {
|
|||
return 0
|
||||
fi
|
||||
case "${prev}" in
|
||||
|
||||
|
||||
--case)
|
||||
COMPREPLY=($(compgen -f "${cur}"))
|
||||
return 0
|
||||
|
@ -115,7 +115,7 @@ complete -F _myapp -o bashdefault -o default myapp
|
|||
#[test]
|
||||
fn bash_with_special_commands() {
|
||||
let mut app = build_app_special_commands();
|
||||
common::<Bash>(&mut app, "my_app", BASH_SPECIAL_CMDS);
|
||||
common(Bash, &mut app, "my_app", BASH_SPECIAL_CMDS);
|
||||
}
|
||||
|
||||
fn build_app_special_commands() -> App<'static> {
|
||||
|
@ -145,7 +145,7 @@ static BASH_SPECIAL_CMDS: &str = r#"_my_app() {
|
|||
my_app)
|
||||
cmd="my_app"
|
||||
;;
|
||||
|
||||
|
||||
help)
|
||||
cmd+="__help"
|
||||
;;
|
||||
|
@ -171,7 +171,7 @@ static BASH_SPECIAL_CMDS: &str = r#"_my_app() {
|
|||
return 0
|
||||
fi
|
||||
case "${prev}" in
|
||||
|
||||
|
||||
*)
|
||||
COMPREPLY=()
|
||||
;;
|
||||
|
@ -179,7 +179,7 @@ static BASH_SPECIAL_CMDS: &str = r#"_my_app() {
|
|||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
;;
|
||||
|
||||
|
||||
my_app__help)
|
||||
opts=" -h -V --help --version "
|
||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
|
||||
|
@ -187,7 +187,7 @@ static BASH_SPECIAL_CMDS: &str = r#"_my_app() {
|
|||
return 0
|
||||
fi
|
||||
case "${prev}" in
|
||||
|
||||
|
||||
*)
|
||||
COMPREPLY=()
|
||||
;;
|
||||
|
@ -202,7 +202,7 @@ static BASH_SPECIAL_CMDS: &str = r#"_my_app() {
|
|||
return 0
|
||||
fi
|
||||
case "${prev}" in
|
||||
|
||||
|
||||
*)
|
||||
COMPREPLY=()
|
||||
;;
|
||||
|
@ -217,7 +217,7 @@ static BASH_SPECIAL_CMDS: &str = r#"_my_app() {
|
|||
return 0
|
||||
fi
|
||||
case "${prev}" in
|
||||
|
||||
|
||||
--config)
|
||||
COMPREPLY=($(compgen -f "${cur}"))
|
||||
return 0
|
||||
|
@ -236,7 +236,7 @@ static BASH_SPECIAL_CMDS: &str = r#"_my_app() {
|
|||
return 0
|
||||
fi
|
||||
case "${prev}" in
|
||||
|
||||
|
||||
--case)
|
||||
COMPREPLY=($(compgen -f "${cur}"))
|
||||
return 0
|
||||
|
@ -257,7 +257,7 @@ complete -F _my_app -o bashdefault -o default my_app
|
|||
#[test]
|
||||
fn bash_with_aliases() {
|
||||
let mut app = build_app_with_aliases();
|
||||
common::<Bash>(&mut app, "cmd", BASH_ALIASES);
|
||||
common(Bash, &mut app, "cmd", BASH_ALIASES);
|
||||
}
|
||||
|
||||
fn build_app_with_aliases() -> App<'static> {
|
||||
|
@ -298,7 +298,7 @@ static BASH_ALIASES: &str = r#"_cmd() {
|
|||
cmd)
|
||||
cmd="cmd"
|
||||
;;
|
||||
|
||||
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
|
@ -312,7 +312,7 @@ static BASH_ALIASES: &str = r#"_cmd() {
|
|||
return 0
|
||||
fi
|
||||
case "${prev}" in
|
||||
|
||||
|
||||
--option)
|
||||
COMPREPLY=($(compgen -f "${cur}"))
|
||||
return 0
|
||||
|
@ -336,7 +336,7 @@ static BASH_ALIASES: &str = r#"_cmd() {
|
|||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
;;
|
||||
|
||||
|
||||
esac
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ fn build_app_with_name(s: &'static str) -> App<'static> {
|
|||
#[test]
|
||||
fn elvish() {
|
||||
let mut app = build_app();
|
||||
common::<Elvish>(&mut app, "my_app", ELVISH);
|
||||
common(Elvish, &mut app, "my_app", ELVISH);
|
||||
}
|
||||
|
||||
static ELVISH: &str = r#"
|
||||
|
@ -77,7 +77,7 @@ set edit:completion:arg-completer[my_app] = [@words]{
|
|||
#[test]
|
||||
fn elvish_with_special_commands() {
|
||||
let mut app = build_app_special_commands();
|
||||
common::<Elvish>(&mut app, "my_app", ELVISH_SPECIAL_CMDS);
|
||||
common(Elvish, &mut app, "my_app", ELVISH_SPECIAL_CMDS);
|
||||
}
|
||||
|
||||
fn build_app_special_commands() -> App<'static> {
|
||||
|
@ -156,7 +156,7 @@ set edit:completion:arg-completer[my_app] = [@words]{
|
|||
#[test]
|
||||
fn elvish_with_aliases() {
|
||||
let mut app = build_app_with_aliases();
|
||||
common::<Elvish>(&mut app, "cmd", ELVISH_ALIASES);
|
||||
common(Elvish, &mut app, "cmd", ELVISH_ALIASES);
|
||||
}
|
||||
|
||||
fn build_app_with_aliases() -> App<'static> {
|
||||
|
|
|
@ -26,7 +26,7 @@ fn build_app_with_name(s: &'static str) -> App<'static> {
|
|||
#[test]
|
||||
fn fish() {
|
||||
let mut app = build_app();
|
||||
common::<Fish>(&mut app, "myapp", FISH);
|
||||
common(Fish, &mut app, "myapp", FISH);
|
||||
}
|
||||
|
||||
static FISH: &str = r#"complete -c myapp -n "__fish_use_subcommand" -s h -l help -d 'Print help information'
|
||||
|
@ -43,7 +43,7 @@ complete -c myapp -n "__fish_seen_subcommand_from help" -s V -l version -d 'Prin
|
|||
#[test]
|
||||
fn fish_with_special_commands() {
|
||||
let mut app = build_app_special_commands();
|
||||
common::<Fish>(&mut app, "my_app", FISH_SPECIAL_CMDS);
|
||||
common(Fish, &mut app, "my_app", FISH_SPECIAL_CMDS);
|
||||
}
|
||||
|
||||
fn build_app_special_commands() -> App<'static> {
|
||||
|
@ -80,7 +80,7 @@ complete -c my_app -n "__fish_seen_subcommand_from help" -s V -l version -d 'Pri
|
|||
#[test]
|
||||
fn fish_with_special_help() {
|
||||
let mut app = build_app_special_help();
|
||||
common::<Fish>(&mut app, "my_app", FISH_SPECIAL_HELP);
|
||||
common(Fish, &mut app, "my_app", FISH_SPECIAL_HELP);
|
||||
}
|
||||
|
||||
fn build_app_special_help() -> App<'static> {
|
||||
|
@ -127,7 +127,7 @@ complete -c my_app -l expansions -d 'Execute the shell command with $SHELL'
|
|||
#[test]
|
||||
fn fish_with_aliases() {
|
||||
let mut app = build_app_with_aliases();
|
||||
common::<Fish>(&mut app, "cmd", FISH_ALIASES);
|
||||
common(Fish, &mut app, "cmd", FISH_ALIASES);
|
||||
}
|
||||
|
||||
fn build_app_with_aliases() -> App<'static> {
|
||||
|
@ -163,7 +163,7 @@ complete -c cmd -s f -s F -l flag -l flg -d 'cmd flag'
|
|||
#[test]
|
||||
fn fish_with_sub_subcommands() {
|
||||
let mut app = build_app_sub_subcommands();
|
||||
common::<Fish>(&mut app, "my_app", FISH_SUB_SUBCMDS);
|
||||
common(Fish, &mut app, "my_app", FISH_SUB_SUBCMDS);
|
||||
}
|
||||
|
||||
fn build_app_sub_subcommands() -> App<'static> {
|
||||
|
|
|
@ -23,10 +23,16 @@ macro_rules! assert_eq {
|
|||
};
|
||||
}
|
||||
|
||||
pub fn common<G: Generator>(app: &mut App, name: &str, fixture: &str) {
|
||||
pub fn common<G: Generator>(gen: G, app: &mut App, name: &str, fixture: &str) {
|
||||
let mut buf = vec![];
|
||||
generate::<G, _>(app, name, &mut buf);
|
||||
generate(gen, app, name, &mut buf);
|
||||
let string = String::from_utf8(buf).unwrap();
|
||||
|
||||
assert_eq!(&string, fixture);
|
||||
assert_eq!(&normalize(&string), &normalize(fixture));
|
||||
}
|
||||
|
||||
fn normalize(string: &str) -> String {
|
||||
use itertools::Itertools;
|
||||
|
||||
string.lines().map(|s| s.trim_end()).join("\n")
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ fn build_app_with_name(s: &'static str) -> App<'static> {
|
|||
#[test]
|
||||
fn powershell() {
|
||||
let mut app = build_app();
|
||||
common::<PowerShell>(&mut app, "my_app", POWERSHELL);
|
||||
common(PowerShell, &mut app, "my_app", POWERSHELL);
|
||||
}
|
||||
|
||||
static POWERSHELL: &str = r#"
|
||||
|
@ -96,7 +96,7 @@ Register-ArgumentCompleter -Native -CommandName 'my_app' -ScriptBlock {
|
|||
#[test]
|
||||
fn powershell_with_special_commands() {
|
||||
let mut app = build_app_special_commands();
|
||||
common::<PowerShell>(&mut app, "my_app", POWERSHELL_SPECIAL_CMDS);
|
||||
common(PowerShell, &mut app, "my_app", POWERSHELL_SPECIAL_CMDS);
|
||||
}
|
||||
|
||||
fn build_app_special_commands() -> App<'static> {
|
||||
|
@ -188,7 +188,7 @@ Register-ArgumentCompleter -Native -CommandName 'my_app' -ScriptBlock {
|
|||
#[test]
|
||||
fn powershell_with_aliases() {
|
||||
let mut app = build_app_with_aliases();
|
||||
common::<PowerShell>(&mut app, "cmd", POWERSHELL_ALIASES);
|
||||
common(PowerShell, &mut app, "cmd", POWERSHELL_ALIASES);
|
||||
}
|
||||
|
||||
fn build_app_with_aliases() -> App<'static> {
|
||||
|
|
|
@ -26,7 +26,7 @@ fn build_app_with_name(s: &'static str) -> App<'static> {
|
|||
#[test]
|
||||
fn zsh() {
|
||||
let mut app = build_app();
|
||||
common::<Zsh>(&mut app, "myapp", ZSH);
|
||||
common(Zsh, &mut app, "myapp", ZSH);
|
||||
}
|
||||
|
||||
static ZSH: &str = r#"#compdef myapp
|
||||
|
@ -106,7 +106,7 @@ _myapp "$@""#;
|
|||
#[test]
|
||||
fn zsh_with_special_commands() {
|
||||
let mut app = build_app_special_commands();
|
||||
common::<Zsh>(&mut app, "my_app", ZSH_SPECIAL_CMDS);
|
||||
common(Zsh, &mut app, "my_app", ZSH_SPECIAL_CMDS);
|
||||
}
|
||||
|
||||
fn build_app_special_commands() -> App<'static> {
|
||||
|
@ -246,7 +246,7 @@ _my_app "$@""#;
|
|||
#[test]
|
||||
fn zsh_with_special_help() {
|
||||
let mut app = build_app_special_help();
|
||||
common::<Zsh>(&mut app, "my_app", ZSH_SPECIAL_HELP);
|
||||
common(Zsh, &mut app, "my_app", ZSH_SPECIAL_HELP);
|
||||
}
|
||||
|
||||
fn build_app_special_help() -> App<'static> {
|
||||
|
@ -308,7 +308,7 @@ _my_app() {
|
|||
'--brackets[List packages \[filter\]]' \
|
||||
'--expansions[Execute the shell command with $SHELL]' \
|
||||
&& ret=0
|
||||
|
||||
|
||||
}
|
||||
|
||||
(( $+functions[_my_app_commands] )) ||
|
||||
|
@ -322,7 +322,7 @@ _my_app "$@""#;
|
|||
#[test]
|
||||
fn zsh_with_nested_subcommands() {
|
||||
let mut app = build_app_nested_subcommands();
|
||||
common::<Zsh>(&mut app, "my_app", ZSH_NESTED_SUBCOMMANDS);
|
||||
common(Zsh, &mut app, "my_app", ZSH_NESTED_SUBCOMMANDS);
|
||||
}
|
||||
|
||||
fn build_app_nested_subcommands() -> App<'static> {
|
||||
|
@ -430,7 +430,7 @@ _my_app "$@""#;
|
|||
#[test]
|
||||
fn zsh_with_aliases() {
|
||||
let mut app = build_app_with_aliases();
|
||||
common::<Zsh>(&mut app, "cmd", ZSH_ALIASES);
|
||||
common(Zsh, &mut app, "cmd", ZSH_ALIASES);
|
||||
}
|
||||
|
||||
fn build_app_with_aliases() -> App<'static> {
|
||||
|
@ -488,7 +488,7 @@ _cmd() {
|
|||
'--flg[cmd flag]' \
|
||||
'::positional:' \
|
||||
&& ret=0
|
||||
|
||||
|
||||
}
|
||||
|
||||
(( $+functions[_cmd_commands] )) ||
|
||||
|
|
|
@ -18,9 +18,9 @@ fn generate_completions() {
|
|||
.arg(Arg::new("debug").short('d')),
|
||||
);
|
||||
|
||||
generate::<Bash, _>(&mut app, "test_app", &mut io::sink());
|
||||
generate::<Fish, _>(&mut app, "test_app", &mut io::sink());
|
||||
generate::<PowerShell, _>(&mut app, "test_app", &mut io::sink());
|
||||
generate::<Elvish, _>(&mut app, "test_app", &mut io::sink());
|
||||
generate::<Zsh, _>(&mut app, "test_app", &mut io::sink());
|
||||
generate(Bash, &mut app, "test_app", &mut io::sink());
|
||||
generate(Fish, &mut app, "test_app", &mut io::sink());
|
||||
generate(PowerShell, &mut app, "test_app", &mut io::sink());
|
||||
generate(Elvish, &mut app, "test_app", &mut io::sink());
|
||||
generate(Zsh, &mut app, "test_app", &mut io::sink());
|
||||
}
|
||||
|
|
|
@ -119,7 +119,7 @@ _my_app() {
|
|||
'--help[Print help information]' \
|
||||
'*::command_with_args:_cmdambivalent' \
|
||||
&& ret=0
|
||||
|
||||
|
||||
}
|
||||
|
||||
(( $+functions[_my_app_commands] )) ||
|
||||
|
@ -149,11 +149,11 @@ complete -c my_app -l help -d 'Print help information'
|
|||
#[test]
|
||||
fn zsh_with_value_hints() {
|
||||
let mut app = build_app_with_value_hints();
|
||||
common::<Zsh>(&mut app, "my_app", ZSH_VALUE_HINTS);
|
||||
common(Zsh, &mut app, "my_app", ZSH_VALUE_HINTS);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fish_with_value_hints() {
|
||||
let mut app = build_app_with_value_hints();
|
||||
common::<Fish>(&mut app, "my_app", FISH_VALUE_HINTS);
|
||||
common(Fish, &mut app, "my_app", FISH_VALUE_HINTS);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,8 @@ use std::ffi::OsString;
|
|||
/// throughout the application representing the normalized values coming from
|
||||
/// the CLI.
|
||||
///
|
||||
/// ```rust
|
||||
#[cfg_attr(not(feature = "derive"), doc = " ```ignore")]
|
||||
#[cfg_attr(feature = "derive", doc = " ```")]
|
||||
/// /// My super CLI
|
||||
/// #[derive(clap::Parser)]
|
||||
/// #[clap(name = "demo")]
|
||||
|
@ -150,7 +151,8 @@ pub trait FromArgMatches: Sized {
|
|||
/// Motivation: If our application had two CLI options, `--name
|
||||
/// <STRING>` and the flag `--debug`, we may create a struct as follows:
|
||||
///
|
||||
/// ```no_run
|
||||
#[cfg_attr(not(feature = "derive"), doc = " ```ignore")]
|
||||
#[cfg_attr(feature = "derive", doc = " ```no_run")]
|
||||
/// struct Context {
|
||||
/// name: String,
|
||||
/// debug: bool
|
||||
|
@ -160,7 +162,8 @@ pub trait FromArgMatches: Sized {
|
|||
/// We then need to convert the `ArgMatches` that `clap` generated into our struct.
|
||||
/// `from_arg_matches` serves as the equivalent of:
|
||||
///
|
||||
/// ```no_run
|
||||
#[cfg_attr(not(feature = "derive"), doc = " ```ignore")]
|
||||
#[cfg_attr(feature = "derive", doc = " ```no_run")]
|
||||
/// # use clap::ArgMatches;
|
||||
/// # struct Context {
|
||||
/// # name: String,
|
||||
|
@ -192,7 +195,8 @@ pub trait FromArgMatches: Sized {
|
|||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
#[cfg_attr(not(feature = "derive"), doc = " ```ignore")]
|
||||
#[cfg_attr(feature = "derive", doc = " ```")]
|
||||
/// #[derive(clap::Parser)]
|
||||
/// struct Args {
|
||||
/// #[clap(flatten)]
|
||||
|
@ -229,7 +233,8 @@ pub trait Args: FromArgMatches + Sized {
|
|||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
#[cfg_attr(not(feature = "derive"), doc = " ```ignore")]
|
||||
#[cfg_attr(feature = "derive", doc = " ```")]
|
||||
/// #[derive(clap::Parser)]
|
||||
/// struct Args {
|
||||
/// #[clap(subcommand)]
|
||||
|
@ -265,7 +270,8 @@ pub trait Subcommand: FromArgMatches + Sized {
|
|||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
#[cfg_attr(not(feature = "derive"), doc = " ```ignore")]
|
||||
#[cfg_attr(feature = "derive", doc = " ```")]
|
||||
/// #[derive(clap::Parser)]
|
||||
/// struct Args {
|
||||
/// #[clap(arg_enum)]
|
||||
|
|
|
@ -31,7 +31,6 @@ pub use crate::{
|
|||
parse::{ArgMatches, Indices, OsValues, Values},
|
||||
};
|
||||
|
||||
#[cfg(feature = "derive")]
|
||||
pub use crate::derive::{ArgEnum, Args, FromArgMatches, IntoApp, Parser, Subcommand};
|
||||
|
||||
#[cfg(feature = "yaml")]
|
||||
|
@ -50,7 +49,6 @@ pub use lazy_static;
|
|||
#[allow(missing_docs)]
|
||||
mod macros;
|
||||
|
||||
#[cfg(feature = "derive")]
|
||||
mod derive;
|
||||
|
||||
#[cfg(feature = "regex")]
|
||||
|
|
Loading…
Reference in a new issue