drag with mouse to select bytes
This commit is contained in:
+101
-43
@@ -19,6 +19,8 @@ pub struct App {
|
||||
|
||||
pub should_quit: bool,
|
||||
|
||||
pub is_dragging_mouse: bool,
|
||||
|
||||
pub logs: Vec<String>,
|
||||
}
|
||||
|
||||
@@ -111,19 +113,23 @@ impl App {
|
||||
|
||||
should_quit: false,
|
||||
|
||||
is_dragging_mouse: false,
|
||||
|
||||
logs: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_events(&mut self, terminal: &mut DefaultTerminal) {
|
||||
self.handle_event(terminal);
|
||||
pub fn handle_events(&mut self, terminal: &mut DefaultTerminal) -> bool {
|
||||
let mut should_redraw = self.handle_event(terminal);
|
||||
|
||||
while event::poll(Duration::ZERO).unwrap() {
|
||||
self.handle_event(terminal);
|
||||
should_redraw |= self.handle_event(terminal);
|
||||
}
|
||||
|
||||
should_redraw
|
||||
}
|
||||
|
||||
pub fn handle_event(&mut self, terminal: &mut DefaultTerminal) {
|
||||
pub fn handle_event(&mut self, terminal: &mut DefaultTerminal) -> bool {
|
||||
let event = event::read()
|
||||
.inspect_err(|error| {
|
||||
#[cfg(target_os = "macos")] {
|
||||
@@ -140,20 +146,24 @@ impl App {
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
// self.logs.push(format!("{event:?}"));
|
||||
|
||||
match event {
|
||||
Event::Resize(_, height) => {
|
||||
self.window_size.rows = height as usize;
|
||||
|
||||
self.buffers[self.current_buffer_index]
|
||||
.clamp_screen_to_primary_cursor(self.window_size);
|
||||
|
||||
true
|
||||
}
|
||||
Event::Key(key_event) => self.handle_key(key_event, terminal),
|
||||
Event::Mouse(mouse_event) => self.handle_mouse(mouse_event),
|
||||
_ => {}
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_key(&mut self, key_event: KeyEvent, terminal: &mut DefaultTerminal) {
|
||||
fn handle_key(&mut self, key_event: KeyEvent, terminal: &mut DefaultTerminal) -> bool {
|
||||
if key_event.modifiers == KeyModifiers::CONTROL &&
|
||||
key_event.code == KeyCode::Char('c')
|
||||
{
|
||||
@@ -163,7 +173,7 @@ impl App {
|
||||
exit(130);
|
||||
}
|
||||
|
||||
let maybe_app_action = self.buffers[self.current_buffer_index].handle_key(
|
||||
let (maybe_app_action, should_redraw) = self.buffers[self.current_buffer_index].handle_key(
|
||||
key_event,
|
||||
&self.config,
|
||||
&self.primary_cursor_register,
|
||||
@@ -182,62 +192,110 @@ impl App {
|
||||
AppAction::Yank => self.yank(),
|
||||
}
|
||||
}
|
||||
|
||||
should_redraw || maybe_app_action.is_some()
|
||||
}
|
||||
|
||||
fn handle_mouse(&mut self, mouse_event: MouseEvent) {
|
||||
let tab_bar_rows = usize::from(self.buffers.len() > 1);
|
||||
fn handle_mouse(&mut self, mouse_event: MouseEvent) -> bool {
|
||||
let position = self.mouse_event_position(mouse_event);
|
||||
let current_buffer = &mut self.buffers[self.current_buffer_index];
|
||||
|
||||
match mouse_event.kind {
|
||||
MouseEventKind::Down(_) => {
|
||||
let byte_column = match mouse_event.column {
|
||||
10..=11 => Some(0),
|
||||
13..=14 => Some(1),
|
||||
16..=17 => Some(2),
|
||||
19..=20 => Some(3),
|
||||
|
||||
23..=24 => Some(4),
|
||||
26..=27 => Some(5),
|
||||
29..=30 => Some(6),
|
||||
32..=33 => Some(7),
|
||||
|
||||
36..=37 => Some(8),
|
||||
39..=40 => Some(9),
|
||||
42..=43 => Some(10),
|
||||
45..=46 => Some(11),
|
||||
|
||||
49..=50 => Some(12),
|
||||
52..=53 => Some(13),
|
||||
55..=56 => Some(14),
|
||||
58..=59 => Some(15),
|
||||
|
||||
_ => None,
|
||||
};
|
||||
|
||||
|
||||
if let Some(byte_column) = byte_column &&
|
||||
mouse_event.row as usize - tab_bar_rows < self.window_size.hex_rows()
|
||||
{
|
||||
current_buffer.primary_cursor = Cursor::at(
|
||||
current_buffer.scroll_position +
|
||||
(mouse_event.row as usize - tab_bar_rows) * BYTES_PER_LINE +
|
||||
byte_column
|
||||
);
|
||||
if let Some(position) = position {
|
||||
current_buffer.primary_cursor = Cursor::at(position);
|
||||
current_buffer.cursors.clear();
|
||||
current_buffer.clamp_screen_to_primary_cursor(self.window_size);
|
||||
self.is_dragging_mouse = true;
|
||||
}
|
||||
|
||||
true
|
||||
},
|
||||
MouseEventKind::Drag(_) if self.is_dragging_mouse => {
|
||||
if let Some(position) = position {
|
||||
current_buffer.primary_cursor.head = position;
|
||||
current_buffer.clamp_screen_to_primary_cursor(self.window_size);
|
||||
}
|
||||
|
||||
true
|
||||
},
|
||||
MouseEventKind::Up(_) if self.is_dragging_mouse => {
|
||||
if let Some(position) = position {
|
||||
current_buffer.primary_cursor.head = position;
|
||||
current_buffer.clamp_screen_to_primary_cursor(self.window_size);
|
||||
}
|
||||
|
||||
self.is_dragging_mouse = false;
|
||||
|
||||
true
|
||||
},
|
||||
MouseEventKind::ScrollDown => {
|
||||
for _ in 0..3 {
|
||||
current_buffer.scroll_down(self.window_size);
|
||||
}
|
||||
|
||||
true
|
||||
},
|
||||
MouseEventKind::ScrollUp => {
|
||||
for _ in 0..3 {
|
||||
current_buffer.scroll_up(self.window_size);
|
||||
}
|
||||
|
||||
true
|
||||
},
|
||||
_ => (),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn mouse_event_position(&self, mouse_event: MouseEvent) -> Option<usize> {
|
||||
let tab_bar_rows = usize::from(self.buffers.len() > 1);
|
||||
|
||||
if usize::from(mouse_event.row) - tab_bar_rows >= self.window_size.hex_rows() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let current_buffer = &self.buffers[self.current_buffer_index];
|
||||
|
||||
let byte_column = match mouse_event.column {
|
||||
10..=11 => Some(0),
|
||||
13..=14 => Some(1),
|
||||
16..=17 => Some(2),
|
||||
19..=20 => Some(3),
|
||||
|
||||
23..=24 => Some(4),
|
||||
26..=27 => Some(5),
|
||||
29..=30 => Some(6),
|
||||
32..=33 => Some(7),
|
||||
|
||||
36..=37 => Some(8),
|
||||
39..=40 => Some(9),
|
||||
42..=43 => Some(10),
|
||||
45..=46 => Some(11),
|
||||
|
||||
49..=50 => Some(12),
|
||||
52..=53 => Some(13),
|
||||
55..=56 => Some(14),
|
||||
58..=59 => Some(15),
|
||||
|
||||
_ => None,
|
||||
};
|
||||
|
||||
byte_column.map(|byte_column| {
|
||||
current_buffer.scroll_position +
|
||||
(mouse_event.row as usize - tab_bar_rows) * BYTES_PER_LINE +
|
||||
byte_column
|
||||
})
|
||||
|
||||
// if let Some(byte_column) = byte_column &&
|
||||
// mouse_event.row as usize - tab_bar_rows < self.window_size.hex_rows()
|
||||
// {
|
||||
// Some(
|
||||
// current_buffer.scroll_position +
|
||||
// (mouse_event.row as usize - tab_bar_rows) * BYTES_PER_LINE +
|
||||
// byte_column
|
||||
// )
|
||||
// } else {
|
||||
// None
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
+15
-5
@@ -121,13 +121,15 @@ impl Buffer {
|
||||
primary_cursor_register: &[u8],
|
||||
other_cursor_registers: &[Vec<u8>],
|
||||
window_size: WindowSize
|
||||
) -> Option<AppAction> {
|
||||
) -> (Option<AppAction>, bool) {
|
||||
let mut should_redraw = !self.alert_message.content.is_empty();
|
||||
self.alert_message = "".into();
|
||||
// self.logs.push(format!("{event:?}"));
|
||||
|
||||
let app_action = match self.partial_action {
|
||||
Some(PartialAction::Replace) => {
|
||||
self.handle_replace(event, window_size);
|
||||
should_redraw = true;
|
||||
None
|
||||
},
|
||||
Some(PartialAction::Repeat) => {
|
||||
@@ -138,9 +140,14 @@ impl Buffer {
|
||||
other_cursor_registers,
|
||||
window_size
|
||||
);
|
||||
should_redraw = true;
|
||||
None
|
||||
},
|
||||
_ => self.handle_other_modes(event, config, window_size),
|
||||
_ => {
|
||||
let (app_action, redraw) = self.handle_other_modes(event, config, window_size);
|
||||
should_redraw |= redraw;
|
||||
app_action
|
||||
},
|
||||
};
|
||||
|
||||
assert!(self.scroll_position.is_multiple_of(BYTES_PER_LINE));
|
||||
@@ -154,7 +161,7 @@ impl Buffer {
|
||||
|
||||
debug_assert!(self.cursors.is_sorted_by_key(|cursor| cursor.head));
|
||||
|
||||
app_action
|
||||
(app_action, should_redraw)
|
||||
}
|
||||
|
||||
fn handle_replace(&mut self, event: KeyEvent, window_size: WindowSize) {
|
||||
@@ -190,17 +197,20 @@ impl Buffer {
|
||||
event: KeyEvent,
|
||||
config: &Config,
|
||||
window_size: WindowSize
|
||||
) -> Option<AppAction> {
|
||||
) -> (Option<AppAction>, bool) {
|
||||
use Action::*;
|
||||
|
||||
let mut result = None;
|
||||
|
||||
let should_reset_partial = self.partial_action.is_some();
|
||||
let mut should_redraw = should_reset_partial;
|
||||
|
||||
if let Some(mode_config) = config.0.get(&self.mode) &&
|
||||
let Some(keybinds) = mode_config.0.get(&self.partial_action) &&
|
||||
let Some(action) = keybinds.0.get(&event.into())
|
||||
{
|
||||
should_redraw = true;
|
||||
|
||||
if action.clears_popups() {
|
||||
self.popups.clear();
|
||||
}
|
||||
@@ -232,7 +242,7 @@ impl Buffer {
|
||||
self.partial_action = None;
|
||||
}
|
||||
|
||||
result
|
||||
(result, should_redraw)
|
||||
}
|
||||
|
||||
fn handle_repeat(
|
||||
|
||||
+9
-6
@@ -33,7 +33,6 @@ const LINES_OF_PADDING: usize = 5;
|
||||
const BYTES_OF_PADDING: usize = LINES_OF_PADDING * BYTES_PER_LINE;
|
||||
|
||||
// TODO:
|
||||
// - click and drag selection
|
||||
// - `go` goto entered offset
|
||||
// - search
|
||||
// - `/` hex, `A-/` ascii
|
||||
@@ -90,12 +89,16 @@ fn main() {
|
||||
crossterm::terminal::enable_raw_mode().unwrap();
|
||||
terminal.backend_mut().queue(EnableMouseCapture).unwrap();
|
||||
|
||||
while !app.should_quit {
|
||||
terminal.draw(|frame| {
|
||||
frame.render_widget(&app, frame.area());
|
||||
}).unwrap();
|
||||
let mut should_redraw = true;
|
||||
|
||||
app.handle_events(&mut terminal);
|
||||
while !app.should_quit {
|
||||
if should_redraw {
|
||||
terminal.draw(|frame| {
|
||||
frame.render_widget(&app, frame.area());
|
||||
}).unwrap();
|
||||
}
|
||||
|
||||
should_redraw = app.handle_events(&mut terminal);
|
||||
}
|
||||
|
||||
terminal.backend_mut().queue(DisableMouseCapture).unwrap();
|
||||
|
||||
Reference in New Issue
Block a user