mark offset

This commit is contained in:
alice pellerin
2026-03-21 01:53:55 -05:00
parent 5716ae804d
commit 1bd5d41123
5 changed files with 62 additions and 32 deletions
+19 -1
View File
@@ -1,4 +1,4 @@
use std::{cmp::min, convert::identity, fs::File, io::Write, iter, mem::{replace, swap}};
use std::{cmp::min, collections::hash_set::Entry, convert::identity, fs::File, io::Write, iter, mem::{replace, swap}};
use ratatui::{style::Stylize, text::Span};
use crate::{BYTES_PER_LINE, app::WindowSize, buffer::{Buffer, Mode, PartialAction}, cursor::Cursor, edit_action::EditAction};
@@ -83,6 +83,8 @@ pub enum Action {
SplitSelectionsInto9s,
JumpToSelectedOffset,
ToggleMark,
}
// actions that act on the app as a whole, not just one buffer
@@ -175,6 +177,8 @@ impl Buffer {
Action::SplitSelectionsInto9s => self.split_selections_into_size(9),
Action::JumpToSelectedOffset => self.jump_to_selected_offset(window_size),
Action::ToggleMark => self.toggle_mark(),
}
None
@@ -646,6 +650,20 @@ impl Buffer {
self.combine_cursors_if_overlapping();
self.clamp_screen_to_primary_cursor(window_size);
}
fn toggle_mark(&mut self) {
match self.marks.entry(self.primary_cursor.lower_bound()) {
Entry::Occupied(occupied_entry) => { occupied_entry.remove(); },
Entry::Vacant(vacant_entry) => vacant_entry.insert(),
}
for cursor in &self.cursors {
match self.marks.entry(cursor.lower_bound()) {
Entry::Occupied(occupied_entry) => { occupied_entry.remove(); },
Entry::Vacant(vacant_entry) => vacant_entry.insert(),
}
}
}
}
// helpers
+5 -1
View File
@@ -1,5 +1,5 @@
use core::slice::GetDisjointMutIndex;
use std::{fs::File, io::Read, path::PathBuf};
use std::{collections::HashSet, fs::File, io::Read, path::PathBuf};
use crossterm::event::KeyEvent;
use ratatui::{style::Color, text::Span};
use crate::{action::AppAction, app::WindowSize, config::Config, cursor::Cursor, edit_action::EditAction};
@@ -16,6 +16,8 @@ pub struct Buffer {
pub primary_cursor: Cursor,
pub cursors: Vec<Cursor>,
pub marks: HashSet<usize>,
pub mode: Mode,
pub partial_action: Option<PartialAction>,
pub partial_replace: Option<u8>,
@@ -86,6 +88,8 @@ impl Buffer {
primary_cursor: Cursor::default(),
cursors: Vec::new(),
marks: HashSet::from([0, 4, 12, 15, 16, 17]),
mode: Mode::Normal,
partial_action: None,
partial_replace: None,
+22 -19
View File
@@ -103,15 +103,9 @@ mod hex {
.iter()
.copied()
.zip((address..).step_by(BYTES_PER_CHUNK))
.map(|(chunk, address)| self.render_chunk(address, &chunk).collect())
.interleave(
(address..)
.step_by(BYTES_PER_CHUNK)
.take(CHUNKS_PER_LINE)
.skip(1)
.map(|address| vec![self.render_large_space_before(address)])
)
.flatten()
.flat_map(|(chunk, address)| {
self.render_chunk(address, &chunk).collect::<Vec<_>>()
})
}
pub fn render_partial_chunks(
@@ -161,6 +155,8 @@ mod hex {
bytes: &[u8; BYTES_PER_CHUNK]
) -> impl Iterator<Item=Span<'static>> {
#[allow(unstable_name_collisions)]
iter::once(self.render_large_space_before(address))
.chain(
bytes
.iter()
.copied()
@@ -172,6 +168,7 @@ mod hex {
.skip(1)
.map(|address| self.render_space_before(address))
)
)
}
fn render_partial_chunk(
@@ -244,30 +241,36 @@ mod hex {
}
fn render_large_space_before(&self, address: usize) -> Span<'static> {
let span: Span = if self.marks.contains(&address) {
"".into()
} else {
" ".into()
};
if iter::once(&self.primary_cursor)
.chain(&self.cursors)
.any(|cursor| cursor.contains_space_before(address))
{
Span {
style: Style::new().bg(Color::select_grey()),
content: " ".into()
}
span.bg(Color::select_grey())
} else {
" ".into()
span
}
}
fn render_space_before(&self, address: usize) -> Span<'static> {
let span: Span = if self.marks.contains(&address) {
"".into()
} else {
" ".into()
};
if iter::once(&self.primary_cursor)
.chain(&self.cursors)
.any(|cursor| cursor.contains_space_before(address))
{
Span {
style: Style::new().bg(Color::select_grey()),
content: " ".into()
}
span.bg(Color::select_grey())
} else {
" ".into()
span
}
}
}
+4
View File
@@ -163,6 +163,8 @@ impl Default for Config {
("9".try_into().unwrap(), Action::SplitSelectionsInto9s),
("J".try_into().unwrap(), Action::JumpToSelectedOffset),
("m".try_into().unwrap(), Action::ToggleMark),
].into()),
(Some(PartialAction::Goto), [
("j".try_into().unwrap(), Action::GotoLineStart),
@@ -234,6 +236,8 @@ impl Default for Config {
("9".try_into().unwrap(), Action::SplitSelectionsInto9s),
("J".try_into().unwrap(), Action::JumpToSelectedOffset),
("m".try_into().unwrap(), Action::ToggleMark),
].into()),
(Some(PartialAction::Space), [
("w".try_into().unwrap(), Action::Save),
+1
View File
@@ -2,6 +2,7 @@
#![allow(clippy::cast_possible_truncation)]
#![feature(get_disjoint_mut_helpers)]
#![feature(exact_bitshifts)]
#![feature(hash_set_entry)]
use app::App;