diff --git a/clap_complete/src/shells/clink.rs b/clap_complete/src/shells/clink.rs new file mode 100644 index 00000000000..0eb48a2e7f4 --- /dev/null +++ b/clap_complete/src/shells/clink.rs @@ -0,0 +1,96 @@ +use crate::{generator::utils, Generator}; +use clap::*; +use std::fmt::Write; + +/// Generate clink completion lua script +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct Clink; + +impl Generator for Clink { + fn file_name(&self, name: &str) -> String { + format!("{name}.lua") + } + + fn generate(&self, cmd: &clap::Command, buf: &mut dyn std::io::prelude::Write) { + let bin_name = cmd + .get_bin_name() + .expect("crate::generate should have set the bin_name"); + + let result = format!( + r#"clink.argmatcher("{bin_name}") +{}"#, + generate_inner(cmd, 0) + ); + w!(buf, result.as_bytes()); + } +} + +fn generate_inner(p: &Command, depth: usize) -> String { + let mut b = String::new(); + let indent = " ".repeat(depth * 4); + + for opt in p.get_opts() { + writeln!(b, "{}:addarg(\"--{}\")", indent, opt.get_id()).unwrap(); + if let Some(help) = opt.get_help() { + writeln!( + b, + "{}:adddescriptions({{\"--{}\", description = \"{}\"}})", + indent, + opt.get_id(), + help + ) + .unwrap(); + if let Some(short) = opt.get_short() { + writeln!( + b, + "{}:adddescriptions({{\"-{}\", description = \"{}\"}})", + indent, short, help + ) + .unwrap() + } + } + } + + for flag in utils::flags(p) { + if let Some(shorts) = flag.get_short_and_visible_aliases() { + for short in shorts { + writeln!(b, "{}:addflags(\"-{}\")", indent, short).unwrap(); + if let Some(help) = flag.get_help() { + writeln!( + b, + "{}:adddescriptions({{\"-{}\", description = \"{}\"}})", + indent, short, help + ) + .unwrap(); + } + } + } + if let Some(longs) = flag.get_long_and_visible_aliases() { + for long in longs { + writeln!(b, "{}:addflags(\"--{}\")", indent, long).unwrap(); + if let Some(help) = flag.get_help() { + writeln!( + b, + "{}:adddescriptions({{\"--{}\", description = \"{}\"}})", + indent, long, help + ) + .unwrap(); + } + } + } + } + + for sub_cmd in p.get_subcommands() { + writeln!( + b, + "{}:addarg({{ \"{}\" .. clink.argmatcher()\n{}{}}})", + indent, + sub_cmd.get_name(), + generate_inner(sub_cmd, depth + 1), + indent + ) + .unwrap(); + } + + b +} diff --git a/clap_complete/src/shells/mod.rs b/clap_complete/src/shells/mod.rs index a08aa878b66..205081243d0 100644 --- a/clap_complete/src/shells/mod.rs +++ b/clap_complete/src/shells/mod.rs @@ -6,6 +6,7 @@ mod fish; mod powershell; mod shell; mod zsh; +mod clink; pub use bash::Bash; pub use elvish::Elvish; @@ -13,3 +14,4 @@ pub use fish::Fish; pub use powershell::PowerShell; pub use shell::Shell; pub use zsh::Zsh; +pub use clink::Clink; diff --git a/clap_complete/src/shells/shell.rs b/clap_complete/src/shells/shell.rs index 52cb2e9b741..263c360ca87 100644 --- a/clap_complete/src/shells/shell.rs +++ b/clap_complete/src/shells/shell.rs @@ -22,6 +22,8 @@ pub enum Shell { PowerShell, /// Z SHell (zsh) Zsh, + /// Clink + Clink, } impl Display for Shell { @@ -65,6 +67,7 @@ impl ValueEnum for Shell { Shell::Fish => PossibleValue::new("fish"), Shell::PowerShell => PossibleValue::new("powershell"), Shell::Zsh => PossibleValue::new("zsh"), + Shell::Clink => PossibleValue::new("clink"), }) } } @@ -77,6 +80,7 @@ impl Generator for Shell { Shell::Fish => shells::Fish.file_name(name), Shell::PowerShell => shells::PowerShell.file_name(name), Shell::Zsh => shells::Zsh.file_name(name), + Shell::Clink => shells::Clink.file_name(name), } } @@ -87,6 +91,7 @@ impl Generator for Shell { Shell::Fish => shells::Fish.generate(cmd, buf), Shell::PowerShell => shells::PowerShell.generate(cmd, buf), Shell::Zsh => shells::Zsh.generate(cmd, buf), + Shell::Clink => shells::Clink.generate(cmd, buf), } } } diff --git a/clap_complete/tests/snapshots/basic.lua b/clap_complete/tests/snapshots/basic.lua new file mode 100644 index 00000000000..f2af44ed996 --- /dev/null +++ b/clap_complete/tests/snapshots/basic.lua @@ -0,0 +1,21 @@ +clink.argmatcher("my-app") +:addflags("-c") +:addflags("-v") +:addflags("-h") +:adddescriptions({"-h", description = "Print help"}) +:addflags("--help") +:adddescriptions({"--help", description = "Print help"}) +:addarg({ "test" .. clink.argmatcher() + :addflags("-d") + :addflags("-c") + :addflags("-h") + :adddescriptions({"-h", description = "Print help"}) + :addflags("--help") + :adddescriptions({"--help", description = "Print help"}) +}) +:addarg({ "help" .. clink.argmatcher() + :addarg({ "test" .. clink.argmatcher() + }) + :addarg({ "help" .. clink.argmatcher() + }) +}) diff --git a/clap_complete/tests/testsuite/clink.rs b/clap_complete/tests/testsuite/clink.rs new file mode 100644 index 00000000000..9d2eecda987 --- /dev/null +++ b/clap_complete/tests/testsuite/clink.rs @@ -0,0 +1,13 @@ +use crate::common; + +#[test] +fn basic() { + let name = "my-app"; + let cmd = common::basic_command(name); + common::assert_matches( + snapbox::file!["../snapshots/basic.lua"], + clap_complete::shells::Clink, + cmd, + name, + ); +} diff --git a/clap_complete/tests/testsuite/main.rs b/clap_complete/tests/testsuite/main.rs index 90ee688a876..a39af0106b6 100644 --- a/clap_complete/tests/testsuite/main.rs +++ b/clap_complete/tests/testsuite/main.rs @@ -6,3 +6,4 @@ mod fish; mod general; mod powershell; mod zsh; +mod clink;