Skip to main content

bawa/ui/
mod.rs

1use crate::input::Input;
2use crossterm::{
3    execute,
4    terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
5};
6use ratatui::{
7    layout::Rect, prelude::CrosstermBackend, DefaultTerminal, Frame, Terminal, TerminalOptions,
8    Viewport,
9};
10use std::{io::stdout, panic, sync::Once};
11
12pub use draw::{draw, draw_fuzzy_finder};
13pub use scroller::Scroller;
14
15pub mod confirmation;
16mod draw;
17mod popup;
18mod scroller;
19
20static ALTERNATE_SCREEN: Once = Once::new();
21
22pub struct Options {
23    pub viewport: Viewport,
24    pub raw_mode: bool,
25    pub alternate_screen: bool,
26}
27
28impl Default for Options {
29    fn default() -> Self {
30        Self {
31            viewport: Viewport::Fullscreen,
32            raw_mode: true,
33            alternate_screen: true,
34        }
35    }
36}
37
38impl From<Options> for TerminalOptions {
39    fn from(value: Options) -> Self {
40        TerminalOptions {
41            viewport: value.viewport,
42        }
43    }
44}
45
46pub fn init() -> DefaultTerminal {
47    init_with_options(Options::default())
48}
49
50pub fn init_inline(height: u16) -> DefaultTerminal {
51    init_with_options(Options {
52        viewport: Viewport::Inline(height),
53        raw_mode: true,
54        alternate_screen: false,
55    })
56}
57
58fn init_with_options(options: Options) -> DefaultTerminal {
59    set_panic_hook();
60
61    if options.raw_mode {
62        enable_raw_mode().expect("Failed to enable raw mode.");
63    }
64
65    if options.alternate_screen {
66        ALTERNATE_SCREEN.call_once(|| {
67            execute!(stdout(), EnterAlternateScreen).expect("Failed to enter alternate screen.");
68        });
69    }
70
71    let backend = CrosstermBackend::new(stdout());
72    Terminal::with_options(backend, options.into()).expect("Failed to initialize terminal.")
73}
74
75fn set_panic_hook() {
76    let default_hook = panic::take_hook();
77
78    panic::set_hook(Box::new(move |info| {
79        restore();
80        default_hook(info);
81    }));
82}
83
84pub fn restore() {
85    disable_raw_mode().expect("Failed to disable raw mode.");
86
87    if ALTERNATE_SCREEN.is_completed() {
88        execute!(stdout(), LeaveAlternateScreen).expect("Failed to leave alternate screen.");
89    }
90}
91
92fn set_cursor(f: &mut Frame, input: &Input, area: Rect) {
93    f.set_cursor_position((area.x + input.cursor_position(), area.y));
94}