6 个版本

0.2.3 2024 年 8 月 7 日
0.2.2 2024 年 6 月 25 日
0.2.1 2024 年 4 月 5 日
0.1.1 2022 年 11 月 29 日

#348命令行界面

Download history 5/week @ 2024-05-20 1/week @ 2024-05-27 122/week @ 2024-06-24 12/week @ 2024-07-01 130/week @ 2024-08-05 6/week @ 2024-08-12

每月 136 次下载

MIT/Apache

29KB
500

tui-menu

Ratatui 提供的菜单小部件。

Demo

特性

  • 子菜单组。
  • 直观的移动。
  • 项目数据是泛型,只要它是可 Clone 的。

尝试

cargo run --example basic

示例

查看 examples/basic.rs

渲染

// menu should be draw at last, so it can stay on top of other content
let menu = Menu::new();
frame.render_stateful_widget(menu, chunks[0], &mut app.menu);

创建嵌套菜单树

注意:MenuItems 可以由任何实现 Clone 的类型创建。使用枚举只是其中一种可行的方法。您也可以使用字符串或您自己的状态类型。

#[derive(Debug, Clone)]
enum Action {
    FileNew,
    FileOpen,
    FileOpenRecent(String),
    FileSaveAs,
    Exit,
    EditCopy,
    EditCut,
    EditPaste,
    AboutAuthor,
    AboutHelp,
}

let menu = MenuState::new(vec![
    MenuItem::group(
        "File",
        vec![
            MenuItem::item("New", Action::FileNew),
            MenuItem::item("Open", Action::FileOpen),
            MenuItem::group(
                "Open recent",
                ["file_1.txt", "file_2.txt"]
                    .iter()
                    .map(|&f| MenuItem::item(f, Action::FileOpenRecent(f.into())))
                    .collect(),
            ),
            MenuItem::item("Save as", Action::FileSaveAs),
            MenuItem::item("Exit", Action::Exit),
        ],
    ),
    MenuItem::group(
        "Edit",
        vec![
            MenuItem::item("Copy", Action::EditCopy),
            MenuItem::item("Cut", Action::EditCut),
            MenuItem::item("Paste", Action::EditPaste),
        ],
    ),
    MenuItem::group(
        "About",
        vec![
            MenuItem::item("Author", Action::AboutAuthor),
            MenuItem::item("Help", Action::AboutHelp),
        ],
    ),
]),

消费事件

for e in menu.drain_events() {
    match e {
        MenuEvent::Selected(item) => match item {
            Action::Exit => {
                return Ok(());
            }
            Action::FileNew => {
                self.content.clear();
            }
            Action::FileOpenRecent(file) => {
                self.content = format!("content of {file}");
            }
            action => {
                self.content = format!("{action:?} not implemented");
            }
        },
    }
    // close the menu once the event has been handled.
    menu.reset();
}

依赖项

~6–12MB
~117K SLoC