hitman 0.12.1

A command line tool for hitting API endpoints
Documentation
use std::{
    io::{self, stdout, Write},
    panic::{set_hook, take_hook},
};

use anyhow::Result;
use crossterm::{
    terminal::{
        disable_raw_mode, enable_raw_mode, EnterAlternateScreen,
        LeaveAlternateScreen,
    },
    ExecutableCommand,
};
use ratatui::{backend::CrosstermBackend, Terminal};

use ui::app::{App, Screen};

mod ui;

#[tokio::main]
async fn main() -> Result<()> {
    init_panic_hook();
    let mut app = App::new()?;

    let screen = CrosstermScreen::new(CrosstermBackend::new(stdout()))?;
    app.run(screen).await?;

    Ok(())
}

pub fn init_panic_hook() {
    let original_hook = take_hook();
    set_hook(Box::new(move |panic_info| {
        let _ = stdout().execute(LeaveAlternateScreen);
        let _ = disable_raw_mode();
        original_hook(panic_info);
    }));
}

#[derive(Default)]
struct CrosstermScreen<W>
where
    W: Write,
{
    terminal: Terminal<CrosstermBackend<W>>,
}

impl<W> CrosstermScreen<W>
where
    W: Write,
{
    fn new(backend: CrosstermBackend<W>) -> io::Result<Self> {
        Ok(Self {
            terminal: Terminal::new(backend)?,
        })
    }
}

impl<W> Screen for CrosstermScreen<W>
where
    W: Write,
{
    type B = CrosstermBackend<W>;

    fn enter(&self) -> io::Result<()> {
        enable_raw_mode()?;
        stdout().execute(EnterAlternateScreen)?;
        Ok(())
    }

    fn leave(&self) -> io::Result<()> {
        stdout().execute(LeaveAlternateScreen)?;
        disable_raw_mode()?;
        Ok(())
    }

    fn terminal(&mut self) -> &mut Terminal<Self::B> {
        &mut self.terminal
    }
}