diff options
Diffstat (limited to 'examples/example-completion/src')
| -rw-r--r-- | examples/example-completion/src/main.rs | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/examples/example-completion/src/main.rs b/examples/example-completion/src/main.rs new file mode 100644 index 0000000..06a0969 --- /dev/null +++ b/examples/example-completion/src/main.rs @@ -0,0 +1,114 @@ +//! `Mingling` Example - Completion +//! +//! # How to Deploy +//! 1. Enable the `comp` feature +//! ```toml +//! mingling = { version = "0.1.5", features = [ +//! "comp", // Enable this feature +//! "parser" +//! ] } +//! ``` +//! +//! 2. Write `build.rs` to generate completion scripts at compile time +//! ```rust +//! use mingling::build::{build_comp_scripts, build_comp_scripts_with_bin_name}; +//! fn main() { +//! // Generate completion scripts for the current program +//! build_comp_scripts().unwrap(); +//! +//! // Or specify a specific name +//! // build_comp_scripts_with_bin_name("your_bin").unwrap(); +//! } +//! ``` +//! +//! 3. Write `main.rs`, adding completion logic for your command entry point +//! 4. Execute `cargo install --path ./`, then run the corresponding completion script in your shell + +use mingling::{ + AnyOutput, Groupped, ShellContext, Suggest, + macros::{chain, completion, dispatcher, gen_program, r_println, renderer, suggest}, + marker::NextProcess, + parser::{Pickable, Picker}, +}; + +// Define dispatcher `FruitCommand`, directing subcommand "fruit" to `FruitEntry` +dispatcher!("fruit", FruitCommand => FruitEntry); + +#[completion(FruitEntry)] +fn comp_fruit_command(ctx: &ShellContext) -> Suggest { + if ctx.current_word.starts_with("-") { + return suggest! { + "--name": "Fruit name", + "--type": "Fruit type" + }; + } + if ctx.previous_word == "--name" { + return suggest!(); + } + if ctx.previous_word == "--type" { + return suggest! { + "apple", "banana" + }; + } + return suggest!(); +} + +#[tokio::main] +async fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CompletionDispatcher); // Add completion dispatcher + program.with_dispatcher(FruitCommand); + program.exec().await; +} + +#[derive(Groupped)] +struct FruitInfo { + name: String, + fruit_type: FruitType, +} + +#[derive(Default, Debug)] +enum FruitType { + #[default] + Apple, + Banana, + Other(String), +} + +impl Pickable for FruitType { + type Output = FruitType; + + fn pick(args: &mut mingling::parser::Argument, flag: mingling::Flag) -> Option<Self::Output> { + let name = args.pick_argument(flag); + match name { + Some(name) => match name.as_str() { + "apple" => Some(FruitType::Apple), + "banana" => Some(FruitType::Banana), + other => Some(FruitType::Other(other.to_string())), + }, + None => None, + } + } +} + +#[chain] +async fn parse_fruit_info(prev: FruitEntry) -> NextProcess { + let picker = Picker::<ThisProgram>::from(prev.inner); + let (fruit_name, fruit_type) = picker.pick("--name").pick("--type").unpack_directly(); + let info = FruitInfo { + name: fruit_name, + fruit_type, + }; + AnyOutput::new(info).route_renderer() +} + +#[renderer] +fn render_fruit(prev: FruitInfo) { + if let FruitType::Other(other) = prev.fruit_type { + r_println!("Fruit name: {}, Type: {:?} (Unknown)", prev.name, other); + } else { + r_println!("Fruit name: {}, Type: {:?}", prev.name, prev.fruit_type); + } +} + +gen_program!(); |
