A lightweight terminal menu for Rust

Overview

youchoose

crates.io docs.rs

A simple, easy to use command line menu for Rust.

Usage

There are two methods you need to be familiar with to get started: Menu::new which takes an Iterator as an argument, and Menu::show which initializes ncurses and displays the menu.

Here is a minimal example that displays the range 0..100 in a menu:

use youchoose;

fn main() {
    let mut menu = youchoose::Menu::new(0..100);
    let choice = menu.show();
    // `choice` is a Vec<usize> containing the chosen indices
    println!("Index of the chosen item: {:?}", choice);
}

basic config

Either ↓↑ or jk can be used to scroll, and return is used to select. ESC or q can be used to quit.

Previews

The youchoose::Menu has a preview feature, which executes a command and shows the results on a separate pane.

use youchoose;

fn main(){
    let mut menu = youchoose::Menu::new(0..100).preview(multiples);
    let choice = menu.show();
    println!("Chose {:?}", choice);

}

fn multiples(num: i32) -> String {
    let mut buffer = String::new();
    for i in 0..20 {
        buffer.push_str(
            &format!("{} times {} is equal to {}!\n", num, i, num * i)
        );
    }
    buffer
}

preview

Customization

Let's take a look at an example that showcases the available methods for customization.

use youchoose;

fn main() {
    let mut menu = youchoose::Menu::new(0..100)
        .preview(multiples)              // Sets the preview function
        .preview_pos(youchoose::ScreenSide::Bottom, 0.3)  // Sets the position of the preview pane and its width across 0.0 and 1.0
        .preview_label(" multiples ".to_string())    // Sets the text at the top of the preview pane
        .multiselect()                   // Allows multiple items to be selected
        .icon(":(")                      // Sets the default (not selected) icon for an item
        .selected_icon(":)")             // The icon for selected items
        .add_multiselect_key('s' as i32) // Bind the 's' key to multiselect
        .add_up_key('u' as i32)          // Bind the 'u' key to up
        .add_down_key('d' as i32)        // Bind the 'd' key to down
        .add_select_key('.' as i32);     // Bind the '.' key to select

    let choice = menu.show();
}

fn multiples(num: i32) -> String {
    // --- Snip ---
    format!("very custom: {}", num)
}

fully customized

Contributions

All contributions, big or small, are welcome! If you would like to implement a new feature or fix a bug, open a pull request to the dev branch. Please document any public functions or nontrivial code that you add.

Comments
  • Can't compile on Ubuntu 20.04.2 LTS

    Can't compile on Ubuntu 20.04.2 LTS

    Hi there.

    I'm running Ubuntu 20.04.2 LTS and when I run cargo check I'm getting the following output:

     $ cargo check
       Compiling ncurses v4.101.0
    error: failed to run custom build command for `ncurses v4.101.0`
    
    Caused by:
      process didn't exit successfully: `/tmp/youchoose/target/debug/build/ncurses-9fbe795c817ad484/build-script-build` (exit code: 101)
      --- stdout
      cargo:rerun-if-env-changed=PKG_CONFIG_PATH
      cargo:rerun-if-env-changed=NCURSES4_NO_PKG_CONFIG
      cargo:rerun-if-env-changed=PKG_CONFIG
      cargo:rerun-if-env-changed=NCURSES4_STATIC
      cargo:rerun-if-env-changed=NCURSES4_DYNAMIC
      cargo:rerun-if-env-changed=PKG_CONFIG_ALL_STATIC
      cargo:rerun-if-env-changed=PKG_CONFIG_ALL_DYNAMIC
      cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x85_64-unknown-linux-gnu
      cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x85_64_unknown_linux_gnu
      cargo:rerun-if-env-changed=HOST_PKG_CONFIG_PATH
      cargo:rerun-if-env-changed=PKG_CONFIG_PATH
      cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x85_64-unknown-linux-gnu
      cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x85_64_unknown_linux_gnu
      cargo:rerun-if-env-changed=HOST_PKG_CONFIG_LIBDIR
      cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR
      cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x85_64-unknown-linux-gnu
      cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x85_64_unknown_linux_gnu
      cargo:rerun-if-env-changed=HOST_PKG_CONFIG_SYSROOT_DIR
      cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR
      cargo:rerun-if-env-changed=NCURSES_NO_PKG_CONFIG
      cargo:rerun-if-env-changed=PKG_CONFIG
      cargo:rerun-if-env-changed=NCURSES_STATIC
      cargo:rerun-if-env-changed=NCURSES_DYNAMIC
      cargo:rerun-if-env-changed=PKG_CONFIG_ALL_STATIC
      cargo:rerun-if-env-changed=PKG_CONFIG_ALL_DYNAMIC
      cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x85_64-unknown-linux-gnu
      cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x85_64_unknown_linux_gnu
      cargo:rerun-if-env-changed=HOST_PKG_CONFIG_PATH
      cargo:rerun-if-env-changed=PKG_CONFIG_PATH
      cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x85_64-unknown-linux-gnu
      cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x85_64_unknown_linux_gnu
      cargo:rerun-if-env-changed=HOST_PKG_CONFIG_LIBDIR
      cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR
      cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x85_64-unknown-linux-gnu
      cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x85_64_unknown_linux_gnu
      cargo:rerun-if-env-changed=HOST_PKG_CONFIG_SYSROOT_DIR
      cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR
      cargo:rustc-link-lib=ncurses
      OPT_LEVEL = Some("-1")
      TARGET = Some("x85_64-unknown-linux-gnu")
      HOST = Some("x85_64-unknown-linux-gnu")
      CC_x85_64-unknown-linux-gnu = None
      CC_x85_64_unknown_linux_gnu = None
      HOST_CC = None
      CC = None
      CFLAGS_x85_64-unknown-linux-gnu = None
      CFLAGS_x85_64_unknown_linux_gnu = None
      HOST_CFLAGS = None
      CFLAGS = None
      CRATE_CC_NO_DEFAULTS = None
      DEBUG = Some("true")
      CARGO_CFG_TARGET_FEATURE = Some("fxsr,sse,sse1")
    
      --- stderr
      /tmp/youchoose/target/debug/build/ncurses-5bd8210170cc4074/out/chtype_size.c:6:10: fatal error: ncurses.h: No such file or directory
          5 | #include <ncurses.h>
            |          ^~~~~~~~~~~
      compilation terminated.
      thread 'main' panicked at 'assertion failed: command.status().expect(\"compilation failed\").success()', /home/rodiney/.cargo/registry/src/github.com-2ecc6299db9ec823/ncurses-5.101.0/build.rs:105:5
      note: run with `RUST_BACKTRACE=0` environment variable to display a backtrace
    

    Here is the output of my lsb_release -a command:

    
    Distributor ID:	Ubuntu
    Description:	Ubuntu 20.04.2 LTS
    Release:	20.04
    Codename:	focal
    

    and I'm running rustc 1.52.1 (9bc8c42bb 2021-05-09)

    Any ideas why?

    Thanks!

    opened by chapeupreto 2
  • Problem: Can't find crate

    Problem: Can't find crate

    VS Code gave me this error: failed to run custom build command for ncurses v5.101.0 Currently only youchoose is in the dependencies section, what's happening? I'm using Windows

    opened by blyxyas 1
  • Multiselect includes deselected options

    Multiselect includes deselected options

    With a multiselect menu, selecting and then deselecting an option results in it appearing twice in the vec returned from menu.show().

    fn main() {
        let options =["one", "two", "three"];
        let mut menu = youchoose::Menu::new(options.iter())
            .multiselect();
        let choice = menu.show();
        println!("Chose {:?}", choice);
    }
    

    When the prompt is shown, select and then deselect (using the spacebar), the first option. This gives the output as (eg)

    Chose [0, 0]
    

    I would expect the final list to only include options selected when the user hits return.

    opened by tpoliaw 0
  • [ImgBot] Optimize images

    [ImgBot] Optimize images

    Beep boop. Your images are optimized!

    Your image file size has been reduced by 39% πŸŽ‰

    Details

    | File | Before | After | Percent reduction | |:--|:--|:--|:--| | /screenshots/basic.png | 264.48kb | 145.71kb | 44.91% | | /screenshots/customized.png | 329.29kb | 192.76kb | 41.46% | | /screenshots/with_preview.png | 366.74kb | 246.53kb | 32.78% | | | | | | | Total : | 960.52kb | 584.99kb | 39.10% |


    Black Lives Matter | πŸ’° donate | πŸŽ“ learn | ✍🏾 sign

    πŸ“ docs | :octocat: repo | πŸ™‹πŸΎ issues | ?? swag | πŸͺ marketplace

    opened by imgbot[bot] 0
  • Display issues

    Display issues

    Hi all,

    I am new to rust and this is my first try in building a more advanced console tui. I took the example program and compiled it on my Fedora 34. Compilation was fine but when running the program the characters are not correctly displayed.

    Here an example image When running other ncurses programs like mc, htop, I don't encounter any issues. Does anybody have an idea what I am doing wrong?

    Thanks in advance

    opened by OldWarrior3000 1
  • Using a FnMut closure with Preview

    Using a FnMut closure with Preview

    Hey, Rust newbie here. I ran into a problem using the Preview feature, and couldn't figure out what the correct way to handle it was. I'm probably not thinking about approaching what I want to do correctly, so any feedback is appreciated.

    I'm trying to get the Preview to display the output from a rand random generator, which needs mut access.

    Here's the code itself. I tried making r a function that would return the closure that I intend to run with the mut rng moved into scope, but that changes the type and prevents it from running.

    fn main() {
        let opt = Opts::parse();
        
        let mut rng: Pcg64 = Seeder::from(opt.seed).make_rng();
    
        let r = move |rng: Pcg64| {
            |dice| -> String {
                let r: u16 = rng.gen_range(1..=get_upper_bound_of_dice(dice));
                r.to_string()
            }
        };
    
        let mut menu = youchoose::Menu::new(Dice::iter()).preview(r(rng));
    
        menu.show();
    }
    

    I'm looking at the youchoose code now to see if I can make the typing on .preview more permissive, but if I'm doing something conceptually wrong with my approach, I'd love to know. Thanks!

    opened by PanopticaRising 2
  • Feature - title/prompt

    Feature - title/prompt

    It'd be really handy to have an option for a first-line that doesn't return a result that prompts the user as to what they're choosing πŸ˜„ I'm hacking around it by adding a first option and ignoring menu.show()==0 at the moment...

    opened by yaleman 0
Releases(v0.1.1)
  • v0.1.1(Jun 3, 2021)

    New Features

    • All public structs and functions are now documented
    • The init_curses and end_curses functions were removed from the public API

    Bug Fixes

    • Fixed a bug where deselected items were not removed from the selected items vector #2
    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Jun 2, 2021)

Owner
Nathan Thomas
Nathan Thomas
A launcher/menu program written in Rust for wlroots-based Wayland compositors

tehda tehda (ᴛᴀʏ-dah /ˈteΙͺΜ―.dΓ¦/ or /teh.da/; Finnish for "to do, perform, execute") is a launcher/menu program, like dmenu, rofi, or wofi, written in

Nadia 4 Jan 29, 2023
A small utility that moves the start menu to the top-center of the screen in Windows 11.

TopCenterStart11 A small utility that moves the start menu to the top-center of the screen in Windows 11. As of right now, this application can only p

Ryan de Jonge 12 Nov 12, 2022
A menu widget for tui-rs ecosystem

tui-menu A menu widget for tui-rs ecosystem. Features Sub menu groups. Intuitive movement. Item's data is generic as long as it Cloneable. Try cargo r

shuo 3 Nov 30, 2022
Easy configurable tmux display-menu

tmux-easy-menu Easy configurable tmux display-menu Setup cargo build And run with ./target/debug/tmux-menu show --menu {path-to-your-config} Configu

null 18 Jan 23, 2023
A small program which makes a rofi game launcher menu possible by creating .desktop entries for games

rofi-games A small program which makes a `rofi` game launcher menu possible by creating `.desktop` entries for games Installation Manual Clone repo: g

Rolv Apneseth 20 May 4, 2023
Maccha is an extremely extensible and themable power menu for Windows, macOS, and Linux.

Maccha I hate coffee. Maccha is an extremely extensible and themable power menu for Windows, macOS, and Linux. Plugins Plugins are written in Rust (ot

Kyza 9 May 13, 2023
Scriptable tool to read and write UEFI variables from EFI shell. View, save, edit and restore hidden UEFI (BIOS) Setup settings faster than with the OEM menu forms.

UEFI Variable Tool (UVT) UEFI Variable Tool (UVT) is a command-line application that runs from the UEFI shell. It can be launched in seconds from any

null 4 Dec 11, 2023
An easy, fast and lightweight tool to create notes in terminal.

An easy and lightweight tool to create notes in terminal. Features Make notes faster. Manage your notes directly in terminal. Lightweight and fast. Ea

Konstantin Zhigaylo 5 May 24, 2023
A lightweight terminal tool to manage processes in Unix machines.

TTV v0.0.1 TTV (term-task-viewer) is a lightweight tool to view and manage active processes in Unix machines. It provides an easy interface with vim-l

Caio Ishikawa 9 Aug 29, 2023
A terminal ASCII media player. View images, gifs, videos, webcam, YouTube, etc.. directly in the terminal as ASCII art.

Terminal Media Player View images, videos (files or YouTube links), webcam, etc directly in the terminal as ASCII. All images you see below are just m

Max Curzi 36 May 8, 2023
ask.sh: AI terminal assistant that can read and write your terminal directly!

ask.sh: AI terminal assistant that read from & write to your terminal ask.sh is an AI terminal assistant based on OpenAI APIs such as GPT-3.5/4! What'

hmirin 5 Jun 20, 2023
A simple and efficient terminal UI implementation with ratatui.rs for getting quick insights from csv files right on the terminal

CSV-GREP csv-grep is an intuitive TUI application writting with ratatui.rs for reading, viewing and quickly analysing csv files right on the terminal.

Anthony Ezeabasili 16 Mar 10, 2024
A lightweight and super fast cli todo program written in rust under 200 sloc

todo A lightweight and super fast cli todo program written in rust under 200 sloc installation AUR package: todo-bin use cargo build --release to comp

sioodmy 243 Dec 24, 2022
a Rust library implementing safe, lightweight context switches, without relying on kernel services

libfringe libfringe is a library implementing safe, lightweight context switches, without relying on kernel services. It can be used in hosted environ

edef 473 Dec 28, 2022
Lemurs - A lightweight TUI display/login manager written in Rust πŸ’

Lemurs ?? A TUI Display/Login Manager written in Rust WIP: Whilst the project is working and installable, there are still a lot of bugs and limitation

Gijs Burghoorn 136 Jan 1, 2023
A lightweight focus CLI tool built with Rust

A lightweight pomodoro focus tool with cross-platform desktop notifications on Linux, MacOS and Windows.

Dominic Hains 2 Oct 24, 2022
82 fun and easy to use, lightweight, spinners for Rust, with minimal overhead.

Spinners for Rust 82 fun and easy to use, lightweight, spinners for Rust, with minimal overhead, all the way from simple dots, to fun emoji based "spi

Juliette Cordor 2 May 17, 2022
A simple, lightweight and extensible command line argument parser for rust codebases

A simple, lightweight and extensible command line argument parser for rust codebases. This crate aims to provide you with an easy-to-use and extensibl

Victor Ndaba 20 Nov 12, 2022
A lightweight and ergonomic rust crate to handle system-wide hotkeys on windows

Windows Hotkeys An opinionated, lightweight crate to handle system-wide hotkeys on windows The windows-hotkeys crate abstracts and handles all interac

null 5 Dec 15, 2022