hexview 0.6.0

A TUI Hex viewer
use ratatui::{
    buffer::Buffer,
    crossterm::event::{Event, KeyCode},
    layout::Rect,
    style::{Color, Style},
    widgets::{Block, Widget},
};

use crate::{line_editor::LineEditor, AppState};

#[derive(Default)]
pub struct Goto {
    pub visible: bool,
    line_editor: LineEditor<'static>,
}

impl Goto {
    pub fn input(&mut self, state: &mut AppState, event: Event) {
        if let Event::Key(key_event) = event {
            match key_event.code {
                KeyCode::Enter => self.goto(state),
                _ => {
                    self.line_editor.input(event);
                }
            }
        }
    }

    pub fn height(&self) -> u16 {
        3 * self.visible as u16
    }

    fn goto(&self, state: &mut AppState) {
        let line = self.line_editor.line();

        if line.is_empty() {
            return;
        }

        if let Some(rest) = line.strip_suffix('%') {
            let Ok(x) = rest.parse::<usize>() else {
                return;
            };
            if x > 100 {
                return;
            }
            state.set_cursor(x * (state.buffer.len() - 1) / 100, state.cursor.length);
        }

        let Ok(x) = usize::from_str_radix(&line, 16) else {
            return;
        };

        if x < state.buffer.len() {
            state.set_cursor(x, state.cursor.length);
        }
    }
}

impl<'a> Widget for &'a Goto {
    fn render(self, area: Rect, buf: &mut Buffer)
    where
        Self: Sized,
    {
        let block = Block::bordered()
            .title(" Go to ")
            .border_style(Style::default().fg(Color::White));

        block.clone().render(area, buf);

        let area = block.inner(area);
        self.line_editor.widget().render(area, buf);
    }
}