This commit is contained in:
2026-02-13 20:04:06 -06:00
commit acd26ab8eb
5 changed files with 1841 additions and 0 deletions

72
src/main.rs Normal file
View File

@@ -0,0 +1,72 @@
use std::{io, time::{Duration, Instant}};
use crossterm::event::{self, Event, KeyCode, KeyEventKind};
use ratatui::{DefaultTerminal, Frame};
use ratatui::layout::{Constraint, Layout, Spacing};
use ratatui::symbols::merge::MergeStrategy;
use ratatui::widgets::Block;
#[derive(Default)]
struct App {
should_exit: bool,
// navigation state goes here (selected index, velocity, etc.)
}
fn main() -> io::Result<()> {
let tick_rate = Duration::from_millis(16); // ~60Hz
let mut last_tick = Instant::now();
ratatui::run(|terminal: &mut DefaultTerminal| {
let mut app = App::default();
while !app.should_exit {
terminal.draw(|f| render(f))?;
// Non-blocking input with timeout until next tick
let timeout = tick_rate.saturating_sub(last_tick.elapsed());
if event::poll(timeout)? {
if let Event::Key(key) = event::read()? {
if key.kind == KeyEventKind::Press {
match key.code {
KeyCode::Char('q') => app.should_exit = true,
// KeyCode::Up/Down etc => update nav intent/state
_ => {}
}
}
}
}
// Tick for time-based navigation / animations
if last_tick.elapsed() >= tick_rate {
// app.on_tick(last_tick.elapsed());
last_tick = Instant::now();
}
}
Ok(())
})
}
fn render(frame: &mut Frame) {
use Constraint::{Fill};
let [top_area, rest_area] = Layout::vertical([Fill(1), Fill(12)]).areas(frame.area());
let [main_area, output_area] = Layout::vertical([Fill(9), Fill(3)])
.spacing(Spacing::Overlap(1))
.areas(rest_area);
let [left_main_area, right_main_area] = Layout::horizontal([Fill(2), Fill(5)])
.spacing(Spacing::Overlap(1))
.areas(main_area);
let [left_output_area, right_output_area] = Layout::horizontal([Fill(5), Fill(1)])
.spacing(Spacing::Overlap(1))
.areas(output_area);
frame.render_widget(Block::bordered(), top_area);
frame.render_widget(Block::bordered().merge_borders(MergeStrategy::Exact), left_output_area);
frame.render_widget(Block::bordered().merge_borders(MergeStrategy::Exact), right_output_area);
frame.render_widget(Block::bordered().merge_borders(MergeStrategy::Exact), left_main_area);
frame.render_widget(Block::bordered().merge_borders(MergeStrategy::Exact), right_main_area);
}