feat(tui): ratatui skeleton with layout
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
17
crates/tui/src/app.rs
Normal file
17
crates/tui/src/app.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
pub struct App {
|
||||
pub should_quit: bool,
|
||||
}
|
||||
|
||||
impl App {
|
||||
pub fn new() -> Self {
|
||||
Self { should_quit: false }
|
||||
}
|
||||
|
||||
pub fn handle_key(&mut self, key: crossterm::event::KeyEvent) {
|
||||
match key.code {
|
||||
crossterm::event::KeyCode::Char('q') => self.should_quit = true,
|
||||
crossterm::event::KeyCode::Esc => self.should_quit = true,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +1,41 @@
|
||||
fn main() {}
|
||||
use clap::Parser;
|
||||
|
||||
mod app;
|
||||
mod ui;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(name = "log-viewer", about = "A log viewer TUI")]
|
||||
struct Cli {
|
||||
/// Log files to open
|
||||
files: Vec<String>,
|
||||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let _cli = Cli::parse();
|
||||
|
||||
crossterm::terminal::enable_raw_mode()?;
|
||||
let mut stdout = std::io::stdout();
|
||||
crossterm::execute!(stdout, crossterm::terminal::EnterAlternateScreen)?;
|
||||
let backend = ratatui::backend::CrosstermBackend::new(stdout);
|
||||
let mut terminal = ratatui::Terminal::new(backend)?;
|
||||
|
||||
let mut app = app::App::new();
|
||||
|
||||
while !app.should_quit {
|
||||
terminal.draw(|frame| ui::render(frame, &app))?;
|
||||
if crossterm::event::poll(std::time::Duration::from_millis(100))?
|
||||
&& let crossterm::event::Event::Key(key) = crossterm::event::read()?
|
||||
{
|
||||
app.handle_key(key);
|
||||
}
|
||||
}
|
||||
|
||||
crossterm::terminal::disable_raw_mode()?;
|
||||
crossterm::execute!(
|
||||
terminal.backend_mut(),
|
||||
crossterm::terminal::LeaveAlternateScreen
|
||||
)?;
|
||||
terminal.show_cursor()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
26
crates/tui/src/ui.rs
Normal file
26
crates/tui/src/ui.rs
Normal file
@@ -0,0 +1,26 @@
|
||||
use crate::app::App;
|
||||
|
||||
pub fn render(frame: &mut ratatui::Frame, _app: &App) {
|
||||
use ratatui::layout::{Constraint, Layout};
|
||||
use ratatui::widgets::{Block, Borders, Paragraph};
|
||||
|
||||
let chunks = Layout::vertical([
|
||||
Constraint::Length(1),
|
||||
Constraint::Min(1),
|
||||
Constraint::Length(1),
|
||||
])
|
||||
.split(frame.area());
|
||||
|
||||
frame.render_widget(
|
||||
Paragraph::new(" Log Viewer").style(ratatui::style::Style::default().bold()),
|
||||
chunks[0],
|
||||
);
|
||||
|
||||
// Main area — 使用 Block::new()(ratatui 0.30 推荐风格)
|
||||
frame.render_widget(
|
||||
Block::new().borders(Borders::ALL).title("No file loaded"),
|
||||
chunks[1],
|
||||
);
|
||||
|
||||
frame.render_widget(Paragraph::new(" Press '?' for help | q to quit"), chunks[2]);
|
||||
}
|
||||
Reference in New Issue
Block a user