aboutsummaryrefslogtreecommitdiff
path: root/src/main/rust
diff options
context:
space:
mode:
authorKevin Hoerr <kjhoerr@submelon.dev>2026-02-27 20:23:28 +0000
committerKevin Hoerr <kjhoerr@submelon.dev>2026-02-27 20:23:28 +0000
commit7b912e839a7e7a30e88cb7876d62c9fc754aa489 (patch)
treed55bb66f4138fd053a4237b6562681cf0ec4d87a /src/main/rust
parent542384b7e3b9dfb0f5aacb35c3d33ca286ce0df0 (diff)
downloadequity-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/main/rust')
-rw-r--r--src/main/rust/main.rs158
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();