modcli/output/input/
menu.rs

1use 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}"); // Highlighted
32            } else {
33                println!("    {option}"); // Normal
34            }
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}