diff --git a/Cargo.toml b/Cargo.toml index b0e303d..810c8a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,4 +13,5 @@ repository = "https://github.com/shuoli84/tui-menu" ratatui = "0.26.1" [dev-dependencies] +color-eyre = "0.6.3" crossterm = "0.27.0" diff --git a/README.md b/README.md index eddcad0..fd23f01 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ A menu widget for [Ratatui](https://crates.io/crates/ratatui). +![Demo](https://vhs.charm.sh/vhs-3pN84WzBTmPTbU2SCtvUiV.gif) + ## Features - Sub menu groups. @@ -23,60 +25,85 @@ take a look at examples/basic.rs ```rust // menu should be draw at last, so it can stay on top of other content let menu = Menu::new(); -f.render_stateful_widget(menu, chunks[0], &mut app.menu); +frame.render_stateful_widget(menu, chunks[0], &mut app.menu); ``` ### Create nested menu tree +Note: MenuItems can be created from any type that implements `Clone`. Using an enum is just one +option which can work. You could use strings or your own state types. + ```rust +#[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", "file.new".into()), - MenuItem::item("Open", "file.open".into()), + MenuItem::item("New", Action::FileNew), + MenuItem::item("Open", Action::FileOpen), MenuItem::group( "Open recent", - vec!["file_1.txt", "file_2.txt"] - .into_iter() - .map(|f| MenuItem::item(f, format!("file.recent:{f}").into())) + ["file_1.txt", "file_2.txt"] + .iter() + .map(|&f| MenuItem::item(f, Action::FileOpenRecent(f.into()))) .collect(), ), - MenuItem::item("Save as", "file.save_as".into()), - MenuItem::item("Exit", "exit".into()), + MenuItem::item("Save as", Action::FileSaveAs), + MenuItem::item("Exit", Action::Exit), ], ), MenuItem::group( "Edit", vec![ - MenuItem::item("Copy", "edit.new".into()), - MenuItem::item("Cut", "edit.cut".into()), - MenuItem::item("Paste", "edit.paste".into()), + MenuItem::item("Copy", Action::EditCopy), + MenuItem::item("Cut", Action::EditCut), + MenuItem::item("Paste", Action::EditPaste), ], ), MenuItem::group( "About", vec![ - MenuItem::item("Author", "about.author".into()), - MenuItem::item("Help", "about.help".into()), + MenuItem::item("Author", Action::AboutAuthor), + MenuItem::item("Help", Action::AboutHelp), ], ), -]); +]), ``` ### Consume events ``` rust -for e in app.menu.drain_events() { +for e in menu.drain_events() { match e { - tui_menu::MenuEvent::Selected(item) => match item.as_ref() { - "exit" => { + MenuEvent::Selected(item) => match item { + Action::Exit => { return Ok(()); } - _ => { - // println!("{} selected", item); + 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(); } ``` diff --git a/demo.tape b/demo.tape new file mode 100644 index 0000000..045c583 --- /dev/null +++ b/demo.tape @@ -0,0 +1,88 @@ +# VHS documentation +# +# Output: +# Output .gif Create a GIF output at the given +# Output .mp4 Create an MP4 output at the given +# Output .webm Create a WebM output at the given +# +# Require: +# Require Ensure a program is on the $PATH to proceed +# +# Settings: +# Set FontSize Set the font size of the terminal +# Set FontFamily Set the font family of the terminal +# Set Height Set the height of the terminal +# Set Width Set the width of the terminal +# Set LetterSpacing Set the font letter spacing (tracking) +# Set LineHeight Set the font line height +# Set LoopOffset % Set the starting frame offset for the GIF loop +# Set Theme Set the theme of the terminal +# Set Padding Set the padding of the terminal +# Set Framerate Set the framerate of the recording +# Set PlaybackSpeed Set the playback speed of the recording +# Set MarginFill Set the file or color the margin will be filled with. +# Set Margin Set the size of the margin. Has no effect if MarginFill isn't set. +# Set BorderRadius Set terminal border radius, in pixels. +# Set WindowBar Set window bar type. (one of: Rings, RingsRight, Colorful, ColorfulRight) +# Set WindowBarSize Set window bar size, in pixels. Default is 40. +# Set TypingSpeed