# Menu ## Introduction A simple command-line menu system in Rust. Works on embedded systems, but also on your command-line. **NOTE:** This crates works only in `&str` - there's no heap allocation, but there's also no automatic conversion to integers, boolean, etc. ```console user@host: ~/menu $ cargo run --example simple Compiling menu v0.5.0 (file:///home/user/menu) Finished dev [unoptimized + debuginfo] target(s) in 0.84 secs Running `target/debug/examples/simple` In enter_root() > help AVAILABLE ITEMS: foo [ ] [ OPTIONS... ] bar sub help [ ] > help foo SUMMARY: foo [ ] [ --verbose ] [ --level=INT ] PARAMETERS: This is the help text for 'a' No help text found --verbose No help text found --level=INT Set the level of the dangle DESCRIPTION: Makes a foo appear. This is some extensive help text. It contains multiple paragraphs and should be preceeded by the parameter list. > foo --level=3 --verbose 1 2 In select_foo. Args = ["--level=3", "--verbose", "1", "2"] a = Ok(Some("1")) b = Ok(Some("2")) verbose = Ok(Some("")) level = Ok(Some("3")) no_such_arg = Err(()) > foo Error: Insufficient arguments given! > foo 1 2 3 3 Error: Too many arguments given > sub /sub> help AVAILABLE ITEMS: baz quux exit help [ ] > exit > help AVAILABLE ITEMS: foo [ ] [ OPTIONS... ] bar sub help [ ] > ^C user@host: ~/menu $ ``` ## Using See `examples/simple.rs` for a working example that runs on Linux or Windows. Here's the menu definition from that example: ```rust const ROOT_MENU: Menu = Menu { label: "root", items: &[ &Item { item_type: ItemType::Callback { function: select_foo, parameters: &[ Parameter::Mandatory { parameter_name: "a", help: Some("This is the help text for 'a'"), }, Parameter::Optional { parameter_name: "b", help: None, }, Parameter::Named { parameter_name: "verbose", help: None, }, Parameter::NamedValue { parameter_name: "level", argument_name: "INT", help: Some("Set the level of the dangle"), }, ], }, command: "foo", help: Some( "Makes a foo appear. This is some extensive help text. It contains multiple paragraphs and should be preceeded by the parameter list. ", ), }, &Item { item_type: ItemType::Callback { function: select_bar, parameters: &[], }, command: "bar", help: Some("fandoggles a bar"), }, &Item { item_type: ItemType::Menu(&Menu { label: "sub", items: &[ &Item { item_type: ItemType::Callback { function: select_baz, parameters: &[], }, command: "baz", help: Some("thingamobob a baz"), }, &Item { item_type: ItemType::Callback { function: select_quux, parameters: &[], }, command: "quux", help: Some("maximum quux"), }, ], entry: Some(enter_sub), exit: Some(exit_sub), }), command: "sub", help: Some("enter sub-menu"), }, ], entry: Some(enter_root), exit: Some(exit_root), }; ``` ## Using with `noline` The [`noline`](https://crates.io/crates/noline) crate is a no-std line-editor with history buffer. You can create a `Runner` using a `noline::Editor` instead of a raw byte slice, and then you will get a `pub fn input_line(&mut self, context: &mut T) -> Result<(), NolineError>` instead of the `pub fn input_byte(&mut self, input: u8, context: &mut T)` you get when you pass a mutable byte slice and let `menu` do the input handling. Call `input_line` and it will use the `noline::Editor` to read a line of text from the user, with history (press 'Up'!) and other nice features. We chose this option as `noline` offers a bunch of benefits, but we didn't want to break everything for people who were quite happy with the basic line editing we have already. See [`examples/noline.rs`](./examples/noline.rs) for an example. ## Changelog See [`CHANGELOG.md`](./CHANGELOG.md). ## License The contents of this repository are dual-licensed under the _MIT OR Apache 2.0_ License. That means you can choose either the MIT license or the Apache 2.0 license when you re-use this code. See [`LICENSE-MIT`](./LICENSE-MIT) or [`LICENSE-APACHE`](./LICENSE-APACHE) for more information on each specific license. Our Apache 2.0 notices can be found in [`NOTICE`](./NOTICE). Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.