tabiew 0.15.1

A lightweight TUI application to view and query tabular data files, such as CSV, TSV, and parquet.
use ratatui::{
    layout::{Constraint, Flex, Layout, Margin, Rect},
    widgets::Paragraph,
};

const MAX_WIDTH: u16 = 64;

pub trait RectExt {
    fn palette(self, height: u16) -> Self;
    fn toast(self, paragraph: &Paragraph) -> Self;
    fn popup(self, paragraph: &Paragraph) -> Self;
    fn goto_line(self, width: u16, height: u16) -> Self;
    fn plot(self) -> Self;
}

impl RectExt for Rect {
    fn palette(self, height: u16) -> Self {
        const WIDTH: u16 = 80;
        const MARGIN_TOP: u16 = 3;
        let [area] = Layout::horizontal([Constraint::Length(WIDTH)])
            .flex(Flex::Center)
            .areas(self);
        let [_, area] =
            Layout::vertical([Constraint::Length(MARGIN_TOP), Constraint::Length(height)])
                .areas(area);
        area
    }

    fn toast(self, paragraph: &Paragraph) -> Self {
        const MARGIN_BOTTOM: u16 = 3;
        let (width, height) = paragraph_size(paragraph);
        let [area] = Layout::horizontal([Constraint::Length(width)])
            .flex(Flex::Center)
            .areas(self);
        let [area, _] = Layout::vertical([
            Constraint::Length(height),
            Constraint::Length(MARGIN_BOTTOM),
        ])
        .flex(Flex::End)
        .areas(area);
        area
    }

    fn popup(self, paragraph: &Paragraph) -> Self {
        let (width, height) = paragraph_size(paragraph);
        self.centered(Constraint::Length(width), Constraint::Length(height))
    }

    fn goto_line(self, width: u16, height: u16) -> Self {
        const MARGIN: u16 = 1;
        let [area, _] = Layout::horizontal([Constraint::Length(width), Constraint::Length(MARGIN)])
            .flex(Flex::End)
            .areas(self);
        let [_, area] =
            Layout::vertical([Constraint::Length(MARGIN), Constraint::Length(height)]).areas(area);
        area
    }

    fn plot(self) -> Self {
        const MARGIN_HORIZONTAL: u16 = 7;
        const MARGIN_VERTICAL: u16 = 3;
        self.inner(Margin::new(MARGIN_HORIZONTAL, MARGIN_VERTICAL))
    }
}

fn paragraph_size(paragraph: &Paragraph) -> (u16, u16) {
    let width = paragraph.line_width().min(MAX_WIDTH as usize) as u16;
    let height = paragraph.line_count(width) as u16;
    (width, height)
}