-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support using heh
as a Ratatui widget
#120
Changes from 4 commits
84f7ee6
255fac0
17f38c5
f919803
0d77149
7397480
91e8db5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,8 @@ | |
|
||
use arboard::Clipboard; | ||
use crossterm::event::{self, Event, KeyEventKind}; | ||
use ratatui::layout::Rect; | ||
use ratatui::Frame; | ||
|
||
use crate::buffer::AsyncBuffer; | ||
use crate::decoder::Encoding; | ||
|
@@ -53,9 +55,9 @@ | |
} | ||
|
||
/// State Information needed by the [`ScreenHandler`] and [`KeyHandler`]. | ||
pub(crate) struct AppData { | ||
pub struct AppData { | ||
/// The file under editing. | ||
pub(crate) file: File, | ||
pub file: File, | ||
|
||
/// The file content. | ||
pub(crate) contents: AsyncBuffer, | ||
|
@@ -117,16 +119,16 @@ | |
|
||
/// Application provides the user interaction interface and renders the terminal screen in response | ||
/// to user actions. | ||
pub(crate) struct Application { | ||
pub struct Application { | ||
/// The application's state and data. | ||
pub(crate) data: AppData, | ||
pub data: AppData, | ||
|
||
/// Renders and displays objects to the terminal. | ||
pub(crate) display: ScreenHandler, | ||
|
||
/// The labels at the bottom of the UI that provide information | ||
/// based on the current offset. | ||
pub(crate) labels: LabelHandler, | ||
pub labels: LabelHandler, | ||
|
||
/// The window that handles keyboard input. This is usually in the form of the Hex/ASCII editor | ||
/// or popups. | ||
|
@@ -138,11 +140,7 @@ | |
/// default. This is called once at the beginning of the program. | ||
/// | ||
/// This errors out if the file specified is empty. | ||
pub(crate) fn new( | ||
file: File, | ||
encoding: Encoding, | ||
offset: usize, | ||
) -> Result<Self, Box<dyn Error>> { | ||
pub fn new(file: File, encoding: Encoding, offset: usize) -> Result<Self, Box<dyn Error>> { | ||
let contents = AsyncBuffer::new(&file)?; | ||
if contents.is_empty() { | ||
eprintln!("heh does not support editing empty files"); | ||
|
@@ -193,11 +191,12 @@ | |
|
||
/// A loop that repeatedly renders the terminal and modifies state based on input. Is stopped | ||
/// when input handling receives CNTRLq, the command to stop. | ||
pub(crate) fn run(&mut self) -> Result<(), Box<dyn Error>> { | ||
pub fn run(&mut self) -> Result<(), Box<dyn Error>> { | ||
ScreenHandler::setup()?; | ||
loop { | ||
self.render_display()?; | ||
if !self.handle_input()? { | ||
let event = event::read()?; | ||
if !self.handle_input(event)? { | ||
break; | ||
} | ||
} | ||
|
@@ -208,15 +207,40 @@ | |
/// Renders the display. This is a wrapper around [`ScreenHandler`'s | ||
/// render](ScreenHandler::render) method. | ||
fn render_display(&mut self) -> Result<(), Box<dyn Error>> { | ||
self.display.render(&mut self.data, &self.labels, self.key_handler.as_ref())?; | ||
Ok(()) | ||
self.display.render(&mut self.data, &self.labels, self.key_handler.as_ref()) | ||
orhun marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
/// Renders a single frame for the given area. | ||
pub fn render_frame(&mut self, frame: &mut Frame, area: Rect) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would you be willing to create an issue so that at some point I remember to create tests specifically for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Beep beep, you got it! |
||
self.data.contents.compute_new_window(self.data.offset); | ||
// We check if we need to recompute the terminal size in the case that the saved off | ||
// variable differs from the current frame, which can occur when a terminal is resized | ||
// between an event handling and a rendering. | ||
if area != self.display.terminal_size { | ||
self.display.terminal_size = area; | ||
self.display.comp_layouts = | ||
ScreenHandler::calculate_dimensions(area, self.key_handler.as_ref()); | ||
// We change the start_address here to ensure that 0 is ALWAYS the first start | ||
// address. We round to preventing constant resizing always moving to 0. | ||
self.data.start_address = (self.data.start_address | ||
+ (self.display.comp_layouts.bytes_per_line / 2)) | ||
/ self.display.comp_layouts.bytes_per_line | ||
* self.display.comp_layouts.bytes_per_line; | ||
} | ||
ScreenHandler::render_frame( | ||
frame, | ||
self.display.terminal_size, | ||
&mut self.data, | ||
&self.labels, | ||
self.key_handler.as_ref(), | ||
&self.display.comp_layouts, | ||
); | ||
} | ||
|
||
/// Handles all forms of user input. This calls out to code in [input], which uses | ||
/// [Application's `key_handler` method](Application::key_handler) to determine what to do for | ||
/// key input. | ||
fn handle_input(&mut self) -> Result<bool, Box<dyn Error>> { | ||
let event = event::read()?; | ||
pub fn handle_input(&mut self, event: Event) -> Result<bool, Box<dyn Error>> { | ||
match event { | ||
Event::Key(key) => { | ||
if key.kind == KeyEventKind::Press { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
pub mod app; | ||
mod buffer; | ||
mod character; | ||
mod chunk; | ||
pub mod decoder; | ||
mod input; | ||
mod label; | ||
pub mod screen; | ||
mod windows; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feel free to add a link to binsider as an example use case of using this as a library!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
Added in 0d77149