diff options
| author | Kevin Hoerr <kjhoerr@submelon.dev> | 2026-02-27 20:23:28 +0000 |
|---|---|---|
| committer | Kevin Hoerr <kjhoerr@submelon.dev> | 2026-02-27 20:23:28 +0000 |
| commit | 7b912e839a7e7a30e88cb7876d62c9fc754aa489 (patch) | |
| tree | d55bb66f4138fd053a4237b6562681cf0ec4d87a /src | |
| parent | 542384b7e3b9dfb0f5aacb35c3d33ca286ce0df0 (diff) | |
| download | equity-tracker-7b912e839a7e7a30e88cb7876d62c9fc754aa489.tar.gz equity-tracker-7b912e839a7e7a30e88cb7876d62c9fc754aa489.tar.bz2 equity-tracker-7b912e839a7e7a30e88cb7876d62c9fc754aa489.zip | |
main.rs: Cordon struct context from main app logic
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/rust/main.rs | 158 |
1 files changed, 77 insertions, 81 deletions
diff --git a/src/main/rust/main.rs b/src/main/rust/main.rs index 2892d7f..db401fe 100644 --- a/src/main/rust/main.rs +++ b/src/main/rust/main.rs @@ -3,24 +3,26 @@ pub mod store; use app::App; use miette::{IntoDiagnostic, Result}; -use ratatui::crossterm::{ - event::{ - self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEvent, KeyEventKind, - }, - execute, - terminal::{EnterAlternateScreen, LeaveAlternateScreen, disable_raw_mode, enable_raw_mode}, -}; use ratatui::{ - DefaultTerminal, Frame, Terminal, + Frame, Terminal, + backend::Backend, buffer::Buffer, layout::Rect, - prelude::CrosstermBackend, style::Stylize, symbols::border, text::{Line, Text}, widgets::{Block, Paragraph, Widget}, }; +use ratatui::crossterm::{ + event::{ + self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEvent, KeyEventKind, + }, + execute, + terminal::{EnterAlternateScreen, LeaveAlternateScreen, disable_raw_mode, enable_raw_mode}, +}; +use ratatui::prelude::CrosstermBackend; + #[cfg(not(tarpaulin_include))] fn main() -> Result<()> { enable_raw_mode().into_diagnostic()?; @@ -31,13 +33,11 @@ fn main() -> Result<()> { let backend = CrosstermBackend::new(stdout); let mut term = Terminal::new(backend).into_diagnostic()?; - let mut ctx = Runtime { - app: App::default(), - }; - ctx.app.init_context()?; + let mut app = App::default(); + app.init_context()?; // could be error, so don't unwrap; let term restore first - let run = ctx.run(&mut term); + let run = run_app(&mut term, &mut app); // restore terminal disable_raw_mode().into_diagnostic()?; @@ -48,54 +48,49 @@ fn main() -> Result<()> { ) .into_diagnostic()?; term.show_cursor().into_diagnostic()?; - run + run?; + Ok(()) } -struct Runtime { - app: App, -} - -impl Runtime { - /// Run the app's main loop until the user quits - #[cfg(not(tarpaulin_include))] - pub fn run(&mut self, terminal: &mut DefaultTerminal) -> Result<()> { - while !self.app.get_exit_status() { - terminal.draw(|frame| self.draw(frame)).into_diagnostic()?; - self.handle_events()?; - } - Ok(()) - } +fn run_app<B: Backend>(term: &mut Terminal<B>, app: &mut App) -> Result<()> { + while !app.get_exit_status() { + term.draw(|frame| draw(frame, app)) + .map_err(|_| std::io::Error::new(std::io::ErrorKind::Other, "idk")) + .into_diagnostic()?; - /// Render app to frame - fn draw(&self, frame: &mut Frame) { - frame.render_widget(self, frame.area()); - } - - /// Use crossterm to read user input events - fn handle_events(&mut self) -> Result<()> { match event::read().into_diagnostic()? { // it's important to check that the event is a key press event as // crossterm also emits key release and repeat events on Windows. Event::Key(key_event) if key_event.kind == KeyEventKind::Press => { - self.handle_key_event(key_event) + handle_key_event(app, key_event)?; } - _ => Ok(()), - } - } - - /// Process user input and run associated app functions - fn handle_key_event(&mut self, key_event: KeyEvent) -> Result<()> { - match key_event.code { - KeyCode::Char('q') => self.app.exit()?, - KeyCode::Left => self.app.decrement_counter()?, - KeyCode::Right => self.app.increment_counter()?, _ => {} }; - Ok(()) } + Ok(()) } -impl Widget for &Runtime { +fn draw(frame: &mut Frame, app: &App) { + let run = Runtime { app }; + frame.render_widget(&run, frame.area()); +} + +/// Process user input and run associated app functions +fn handle_key_event(app: &mut App, key_event: KeyEvent) -> Result<()> { + match key_event.code { + KeyCode::Char('q') => app.exit()?, + KeyCode::Left => app.decrement_counter()?, + KeyCode::Right => app.increment_counter()?, + _ => {} + }; + Ok(()) +} + +struct Runtime<'a> { + app: &'a App, +} + +impl<'a> Widget for &Runtime<'a> { fn render(self, area: Rect, buf: &mut Buffer) { let title = Line::from(" Counter App Tutorial ".bold()); let instructions = Line::from(vec![ @@ -130,19 +125,15 @@ mod tests { use app::OverflowError; use ratatui::style::Style; - fn default_runtime() -> Runtime { - let mut app = App::default(); - assert!(app.init_context().is_ok()); - Runtime { app } - } - #[test] fn render() { - let ctx = default_runtime(); + let mut app = App::default(); + assert!(app.init_context().is_ok()); + let runtime = Runtime { app: &app }; let mut buf = Buffer::empty(Rect::new(0, 0, 50, 4)); - ctx.render(buf.area, &mut buf); + runtime.render(buf.area, &mut buf); let mut expected = Buffer::with_lines(vec![ "┏━━━━━━━━━━━━━ Counter App Tutorial ━━━━━━━━━━━━━┓", @@ -165,59 +156,63 @@ mod tests { #[test] fn handle_key_event_inc_dec() { - let mut ctx = default_runtime(); - - let res = ctx.handle_key_event(KeyCode::Right.into()); + let mut app = App::default(); + assert!(app.init_context().is_ok()); + let res = handle_key_event(&mut app, KeyCode::Right.into()); assert!(res.is_ok()); - assert_eq!(ctx.app.display_counter(), "1"); + assert_eq!(app.display_counter(), "1"); - let res = ctx.handle_key_event(KeyCode::Left.into()); + let res = handle_key_event(&mut app, KeyCode::Left.into()); assert!(res.is_ok()); - assert_eq!(ctx.app.display_counter(), "0"); + assert_eq!(app.display_counter(), "0"); } #[test] fn handle_key_event_inc_n() { - let mut ctx = default_runtime(); + let mut app = App::default(); + assert!(app.init_context().is_ok()); let n = 8; for i in 1..=n { - let res = ctx.handle_key_event(KeyCode::Right.into()); + let res = handle_key_event(&mut app, KeyCode::Right.into()); assert!(res.is_ok()); - assert_eq!(ctx.app.display_counter(), i.to_string()); + assert_eq!(app.display_counter(), i.to_string()); } - assert_eq!(ctx.app.display_counter(), n.to_string()); + assert_eq!(app.display_counter(), n.to_string()); } #[test] fn handle_key_event_inc_n_dec() { - let mut ctx = default_runtime(); + let mut app = App::default(); + assert!(app.init_context().is_ok()); let n = 8; for i in 1..=n { - let res = ctx.handle_key_event(KeyCode::Right.into()); + let res = handle_key_event(&mut app, KeyCode::Right.into()); assert!(res.is_ok()); - assert_eq!(ctx.app.display_counter(), i.to_string()); + assert_eq!(app.display_counter(), i.to_string()); } - assert_eq!(ctx.app.display_counter(), n.to_string()); + assert_eq!(app.display_counter(), n.to_string()); - let res = ctx.handle_key_event(KeyCode::Left.into()); + let res = handle_key_event(&mut app, KeyCode::Left.into()); assert!(res.is_ok()); - assert_eq!(ctx.app.display_counter(), (n - 1).to_string()); + assert_eq!(app.display_counter(), (n - 1).to_string()); } #[test] fn handle_key_event_exit() { - let mut ctx = default_runtime(); - let res = ctx.handle_key_event(KeyCode::Char('q').into()); + let mut app = App::default(); + assert!(app.init_context().is_ok()); + let res = handle_key_event(&mut app, KeyCode::Char('q').into()); assert!(res.is_ok()); - assert!(ctx.app.get_exit_status()); + assert!(app.get_exit_status()); } #[test] fn handle_key_event_dec_error() { - let mut ctx = default_runtime(); - let res = ctx.handle_key_event(KeyCode::Left.into()); + let mut app = App::default(); + assert!(app.init_context().is_ok()); + let res = handle_key_event(&mut app, KeyCode::Left.into()); assert!(res.is_err()); let res_err = res.unwrap_err(); @@ -237,12 +232,13 @@ mod tests { #[test] fn handle_key_event_inc_error() { - let mut ctx = default_runtime(); + let mut app = App::default(); + assert!(app.init_context().is_ok()); // no pub set_counter exposed, so we manually set this for _ in 0..u8::MAX { - assert!(ctx.app.increment_counter().is_ok()); + assert!(app.increment_counter().is_ok()); } - let res = ctx.handle_key_event(KeyCode::Right.into()); + let res = handle_key_event(&mut app, KeyCode::Right.into()); assert!(res.is_err()); let res_err = res.unwrap_err(); |
