modcli/output/input/
menu.rs1use crate::output::{hook, print};
2use crossterm::{
3 cursor,
4 event::{self, Event, KeyCode},
5 execute,
6 terminal::{self, ClearType},
7};
8use std::io::{stdout, Write};
9
10pub fn interactive_menu() -> Option<usize> {
11 let mut stdout = stdout();
12 let options = ["🍕 Pizza", "🍔 Burger", "🌮 Taco", "❌ Exit"];
13 let mut selected = 0;
14
15 if let Err(e) = terminal::enable_raw_mode() {
16 hook::error(&format!("failed to enable raw mode: {e}"));
17 return None;
18 }
19 if let Err(e) = execute!(stdout, terminal::Clear(ClearType::All)) {
20 hook::warn(&format!("failed to clear terminal: {e}"));
21 }
22
23 loop {
24 if let Err(e) = execute!(stdout, cursor::MoveTo(0, 0)) {
25 hook::warn(&format!("failed to move cursor: {e}"));
26 }
27
28 println!("\nPick your poison:\n");
29 for (i, option) in options.iter().enumerate() {
30 if i == selected {
31 println!(" > {option}"); } else {
33 println!(" {option}"); }
35 }
36
37 if let Err(e) = stdout.flush() {
38 hook::warn(&format!("flush failed: {e}"));
39 }
40 match event::read() {
41 Ok(Event::Key(key_event)) => match key_event.code {
42 KeyCode::Up => {
43 selected = selected.saturating_sub(1);
44 }
45 KeyCode::Down => {
46 if selected < options.len() - 1 {
47 selected += 1;
48 }
49 }
50 KeyCode::Enter => {
51 if let Err(e) = terminal::disable_raw_mode() {
52 hook::warn(&format!("disable raw mode failed: {e}"));
53 }
54 return Some(selected);
55 }
56 KeyCode::Esc => {
57 if let Err(e) = terminal::disable_raw_mode() {
58 hook::warn(&format!("disable raw mode failed: {e}"));
59 }
60 return None;
61 }
62 _ => {}
63 },
64 Ok(_) => {}
65 Err(e) => {
66 print::warn(&format!("event read failed: {e}"));
67 }
68 }
69 }
70}