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.
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 <a> [ <b> ] [ OPTIONS... ]
bar
sub
help [ <command> ]
> help foo
SUMMARY:
foo <a> [ <b> ] [ --verbose ] [ --level=INT ]
PARAMETERS:
<a>
This is the help text for 'a'
<b>
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 [ <command> ]
> exit
> help
AVAILABLE ITEMS:
foo <a> [ <b> ] [ OPTIONS... ]
bar
sub
help [ <command> ]
> ^C
user@host: ~/menu $
See examples/simple.rs
for a working example that runs on Linux or Windows. Here's the menu definition from that example:
const ROOT_MENU: Menu<Output> = 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),
};
noline
The 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
for an example.
See CHANGELOG.md
.
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
or
LICENSE-APACHE
for more information on each specific
license. Our Apache 2.0 notices can be found in 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.