Add Ratatui terminal application
This commit is contained in:
81
crates/tui/src/main.rs
Normal file
81
crates/tui/src/main.rs
Normal file
@@ -0,0 +1,81 @@
|
||||
mod app;
|
||||
mod editor;
|
||||
mod ui;
|
||||
|
||||
use std::{env, error::Error, io, time::Duration};
|
||||
|
||||
use crossterm::{
|
||||
event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyEventKind},
|
||||
execute,
|
||||
};
|
||||
use gotcha_gitea::Config;
|
||||
|
||||
const HELP: &str = "\
|
||||
Gotcha TUI
|
||||
|
||||
Usage: gotcha-tui [--server SERVER]
|
||||
|
||||
Keyboard:
|
||||
1..5 switch Home, Issues, Repos, PRs, Milestones
|
||||
j/k, arrows move selection
|
||||
n/p or ]/[ next/previous page
|
||||
Enter open selected item
|
||||
Backspace go back (edits text inside an editor)
|
||||
a/e/c/x/d add, edit, comment, toggle state, delete
|
||||
/, v, b, * filters, activity filter, branch, repository favorite
|
||||
f browse files from a repository commit view
|
||||
r reload
|
||||
s choose or manage servers
|
||||
, edit TUI preferences
|
||||
q back, or quit from a root pane
|
||||
|
||||
Editors use Tab/Shift-Tab between fields, normal cursor/editing keys, Ctrl-S to
|
||||
save, and Esc to cancel. Mouse clicks select items, double-click opens them,
|
||||
and the scroll wheel moves through lists.";
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn Error>> {
|
||||
let requested_server = parse_args()?;
|
||||
let config = Config::load()?;
|
||||
let mut app = app::App::new(config, requested_server.as_deref()).await?;
|
||||
|
||||
let mut terminal = ratatui::init();
|
||||
execute!(io::stdout(), EnableMouseCapture)?;
|
||||
let result = run(&mut terminal, &mut app).await;
|
||||
execute!(io::stdout(), DisableMouseCapture)?;
|
||||
ratatui::restore();
|
||||
result
|
||||
}
|
||||
|
||||
async fn run(
|
||||
terminal: &mut ratatui::DefaultTerminal,
|
||||
app: &mut app::App,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
while !app.should_quit {
|
||||
terminal.draw(|frame| ui::draw(frame, app))?;
|
||||
if event::poll(Duration::from_millis(100))? {
|
||||
match event::read()? {
|
||||
Event::Key(key) if key.kind == KeyEventKind::Press => app.handle_key(key).await,
|
||||
Event::Mouse(mouse) => app.handle_mouse(mouse).await,
|
||||
Event::Resize(_, _) => {}
|
||||
_ => {}
|
||||
}
|
||||
} else if app.should_auto_reload() {
|
||||
app.reload().await;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_args() -> Result<Option<String>, String> {
|
||||
let args: Vec<_> = env::args().skip(1).collect();
|
||||
match args.as_slice() {
|
||||
[] => Ok(None),
|
||||
[help] if matches!(help.as_str(), "-h" | "--help" | "help") => {
|
||||
println!("{HELP}");
|
||||
std::process::exit(0);
|
||||
}
|
||||
[option, server] if option == "--server" => Ok(Some(server.clone())),
|
||||
_ => Err(format!("invalid arguments\n\n{HELP}")),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user