#dmenu #menu #ui

nightly dm_x

A library for using dmenu as an option picker

4 releases

0.2.3 Jun 21, 2022
0.2.1 Jun 15, 2022
0.2.0 Jun 15, 2022
0.1.1 Jun 14, 2022
0.1.0 Jun 13, 2022

#733 in GUI

MIT license

19KB
308 lines

dm_x

A Rust crate for using dmenu, a keyboard-driven menu originally written for use with tiling window managers.

Using this crate involves implementing the Item trait for your type, and then passing a slice of those to the Dmx::select() method.

Item is already implemented for &str, so the following should work:

let choices: &[&str] = &[
    "Choice A",
    "Choice B",
    "Choice C",
    "Both A and B",
    "Both B and C",
    "All Three",
    "None of the Above",
];

let dmx = Dmx::default();

match dmx.select("Pick One:", choices).unwrap() {
    None => {
        println!("You declined to select an option.");
    },
    Some(n) => match choices.get(n) {
        None => {
            println!("You somehow chose an invalid choice.");
        },
        Some(choice) => {
            println!("You chose \"{}\".", choice);
        }
    }
}

See the examples/ for non-trivial implementation of Item.


lib.rs:

dm_x is a library to facilitate using dmenu as a way for a user to select from a list of options.

dmenu is a great tool for keyboard-driven environments, as it allows selection of options in a way that's faster and more convenient than clicking on an item in a list, or selecting from a drop-down. This small library offers three things when it comes to using this tool:

  • A convenient way to interact with dmenu---both in feeding it options and in reporting which was selected.
  • Separating the text of an option offered by dmenu from the programmatinc function of that option.
  • A mechanism for providing the user with an easily-typeable mnemonic along with more descriptive option text (both of which are, again, distinct from the function of the option in question).

Obviously, you are going to need dmenu installed (and a system where it can run).

static REGRESSION_TYPES: &[(&str, &str)] = &[
("linear", "Linear Regression"),
("p2", "Quadratic Regression"),
("p3", "Cubic Regression"),
("log", "Logistic Regression"),
("ln", "Logarithmic Regression"),
("sin", "Sinusoidal Regression")
];

let dmx = Dmx::default();

match dmx.select("method:", REGRESSION_TYPES).unwrap() {
Some(n) => {
println!("{}", REGRESSION_TYPES[n].1);
},
None => {
println!("No regression type chosen.");
},
}

Features

dm_x has one optional feature, config, which provides the ability to deserialize a Dmx configuration from some .toml. This gets serde (and toml) involved, which is kind of a large dependency for an otherwise dependency-free (save the dmenu binary) crate (hence the feature gate).

#[cfg(feature = "config")]
{
const CHOICES: &[(&str, &str)] = &[
("frog", "a Fire-Breathing, Blue-Winged Frog"),
("toad", "a Acid-Blooded, Orange-Eyed Toad"),
("cat", "a Psychic Cat (Can Kill You With Its Mind)"),
("rat", "a Venom-Fanged Skaven Warlock"),
("dog", "Just a Regular Border Collie")
];

let dmx = Dmx::from_file("test/dmx_conf.toml").unwrap();

match dmx.select("->", CHOICES).unwrap() {
None => {
println!("You have chosen to adventure alone.");
},
Some(n) => {
println!("You will be accompanied by {}", CHOICES[n].1);
}
}
}

Examination of the included "test/dmx_conf.toml" file should make the required format fairly obvious; all values are optional (defaulting to the values provided by Dmx::default()) and should be just as dmenu would expect them as arguments.

File "test/dmx_conf.toml":

dmenu     = "/usr/bin/dmenu"
font      = "Terminus-12"
normal_bg = "#88cccc"
normal_fg = "#422"
select_bg = "#422"
select_fg = "#88cccc"

Dependencies

~200KB