diff --git a/src/buffer.rs b/src/buffer.rs index df30445..12a30c1 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -1,9 +1,8 @@ -use core::slice::GetDisjointMutIndex; use std::{collections::HashSet, fs::File, io::{self, Read}, path::PathBuf}; use crossterm::event::KeyEvent; use ratatui::{style::Stylize, text::Span}; use serde::{Deserialize, Serialize}; -use crate::{BYTES_PER_LINE, action::{Action, AppAction}, buffer::actions::bytes_to_nat, config::Config, cursor::Cursor, edit_action::EditAction, popup::Popup, window_size::WindowSize}; +use crate::{BYTES_PER_LINE, action::{Action, AppAction}, buffer::actions::bytes_to_nat, config::Config, cursor::Cursor, edit_action::EditAction, popup::Popup, utilities::IsOverlapping, window_size::WindowSize}; mod widget; mod actions; diff --git a/src/buffer/actions.rs b/src/buffer/actions.rs index 3439d59..b6d56c3 100644 --- a/src/buffer/actions.rs +++ b/src/buffer/actions.rs @@ -1,4 +1,4 @@ -use std::{cmp::min, collections::hash_set::Entry, convert::identity, fs::File, io::Write, iter, mem::{replace, swap}}; +use std::{cmp::min, convert::identity, fs::File, io::Write, iter, mem::{replace, swap}}; use itertools::Itertools; use ratatui::{style::{Color, Stylize}, text::Span}; use crate::{BYTES_OF_PADDING, BYTES_PER_LINE, LINES_OF_PADDING, action::BufferAction, buffer::{Buffer, InspectionStatus, Mode, PartialAction}, cursor::Cursor, edit_action::EditAction, popup::Popup, utilities::{Floorable, SaturatingSubtract}, window_size::WindowSize}; @@ -467,20 +467,18 @@ impl Buffer { } 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(), + if !self.marks.insert(self.primary_cursor.lower_bound()) { + self.marks.remove(&self.primary_cursor.lower_bound()); } 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(), + if !self.marks.insert(cursor.lower_bound()) { + self.marks.remove(&cursor.lower_bound()); } } } - const fn align_view_center(&mut self, window_size: WindowSize) { + fn align_view_center(&mut self, window_size: WindowSize) { let half_a_screen = window_size.visible_byte_count() / 2; self.scroll_position = self.primary_cursor.head @@ -499,7 +497,7 @@ impl Buffer { .min(self.max_contents_index().floored_to_the_nearest(BYTES_PER_LINE)); } - const fn align_view_top(&mut self, window_size: WindowSize) { + fn align_view_top(&mut self, window_size: WindowSize) { self.scroll_position = self.primary_cursor.head .floored_to_the_nearest(BYTES_PER_LINE) .saturating_sub(self.top_padding(window_size)); @@ -676,7 +674,7 @@ fn inspect(selection: &[u8]) -> Vec> { let utf8 = str::from_utf8(selection).ok() .filter(|_| selection.len() != 1) - .map(|utf8| utf8.trim_suffix('\0')) + .map(|utf8| utf8.trim_end_matches('\0')) .filter(|utf8| !utf8.contains(is_illegal_control_character)) .map(|utf8| Span::from(format!("\"{utf8}\"")).red()); @@ -830,7 +828,7 @@ impl Buffer { } } - pub const fn clamp_screen_to_contents(&mut self, window_size: WindowSize) { + pub fn clamp_screen_to_contents(&mut self, window_size: WindowSize) { let max_scroll_position = self.max_contents_index() .floored_to_the_nearest(BYTES_PER_LINE) .saturating_sub(Self::bottom_padding(window_size)); @@ -868,7 +866,11 @@ pub fn bytes_to_nat(bytes: &[u8]) -> Option { .rev() // little-endian .skip_while(|&&byte| byte == 0) .try_fold(u64::default(), |result, &byte| { - Some(result.shl_exact(8)? | u64::from(byte)) + if result.leading_zeros() < 8 { + None + } else { + Some((result << 8) | u64::from(byte)) + } }) } diff --git a/src/cursor/actions.rs b/src/cursor/actions.rs index 4d13c92..4099371 100644 --- a/src/cursor/actions.rs +++ b/src/cursor/actions.rs @@ -93,7 +93,7 @@ impl Cursor { } } - pub const fn goto_line_start(&mut self) { + pub fn goto_line_start(&mut self) { self.extend_line_start(); self.collapse(); } @@ -108,12 +108,12 @@ impl Cursor { self.collapse(); } - pub const fn goto_file_end(&mut self, max: usize) { + pub fn goto_file_end(&mut self, max: usize) { self.extend_file_end(max); self.collapse(); } - pub const fn extend_line_start(&mut self) { + pub fn extend_line_start(&mut self) { self.head.floor_to_the_nearest(BYTES_PER_LINE); } @@ -128,7 +128,7 @@ impl Cursor { self.head %= BYTES_PER_LINE; } - pub const fn extend_file_end(&mut self, max: usize) { + pub fn extend_file_end(&mut self, max: usize) { self.head += previous_multiple_of(BYTES_PER_LINE, max + 1 - self.head); } @@ -156,7 +156,7 @@ impl Cursor { } } - pub const fn move_previous_word_start(&mut self) { + pub fn move_previous_word_start(&mut self) { if self.head == 0 { return; } self.collapse(); @@ -188,7 +188,7 @@ impl Cursor { } } - pub const fn extend_previous_word_start(&mut self) { + pub fn extend_previous_word_start(&mut self) { if self.head == 0 { return; } if self.head.is_multiple_of(4) { // at the beginning of a word @@ -236,7 +236,7 @@ impl Cursor { } } -const fn previous_multiple_of(multiple: usize, number: usize) -> usize { +fn previous_multiple_of(multiple: usize, number: usize) -> usize { number.saturating_sub(1).floored_to_the_nearest(multiple) } diff --git a/src/main.rs b/src/main.rs index ab61efd..37e1831 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,6 @@ #![warn(clippy::pedantic, clippy::nursery)] #![allow(clippy::cast_possible_truncation)] #![allow(clippy::enum_glob_use)] -#![feature(get_disjoint_mut_helpers)] -#![feature(exact_bitshifts)] -#![feature(hash_set_entry)] -#![feature(trim_prefix_suffix)] -#![feature(const_trait_impl)] use arguments::Arguments; use clap::Parser; diff --git a/src/utilities.rs b/src/utilities.rs index ec8d1bc..3b08f6a 100644 --- a/src/utilities.rs +++ b/src/utilities.rs @@ -3,9 +3,11 @@ mod empty_span; mod custom_greys; mod floor_to_the_nearest; mod saturating_subtract; +mod is_overlapping; pub use cardinality::HasCardinality; pub use empty_span::empty_span; pub use custom_greys::CustomGreys; pub use floor_to_the_nearest::Floorable; pub use saturating_subtract::SaturatingSubtract; +pub use is_overlapping::IsOverlapping; diff --git a/src/utilities/floor_to_the_nearest.rs b/src/utilities/floor_to_the_nearest.rs index 8ebbde5..6442c16 100644 --- a/src/utilities/floor_to_the_nearest.rs +++ b/src/utilities/floor_to_the_nearest.rs @@ -1,10 +1,10 @@ -pub const trait Floorable { +pub trait Floorable { fn floor_to_the_nearest(&mut self, step: Self); fn floored_to_the_nearest(self, step: Self) -> Self; } -const impl Floorable for usize { +impl Floorable for usize { fn floor_to_the_nearest(&mut self, step: Self) { *self -= *self % step; } diff --git a/src/utilities/is_overlapping.rs b/src/utilities/is_overlapping.rs new file mode 100644 index 0000000..20d4ece --- /dev/null +++ b/src/utilities/is_overlapping.rs @@ -0,0 +1,11 @@ +use std::ops::RangeInclusive; + +pub trait IsOverlapping { + fn is_overlapping(&self, other: &Self) -> bool; +} + +impl IsOverlapping for RangeInclusive { + fn is_overlapping(&self, other: &Self) -> bool { + self.contains(other.start()) || self.contains(other.end()) + } +}