#[derive(PartialEq, Copy, Clone, Default, Debug)]
pub enum CursorSelects {
#[default]
LeftNibble,
RightNibble,
AsciiChar,
}
#[derive(Copy, Clone, Default)]
pub struct Cursor {
pos: usize,
sel: CursorSelects,
}
impl Cursor {
pub fn is_over_left_nibble(&self) -> bool {
self.sel == CursorSelects::LeftNibble
}
pub fn is_over_right_nibble(&self) -> bool {
self.sel == CursorSelects::RightNibble
}
pub fn is_over_ascii(&self) -> bool {
self.sel == CursorSelects::AsciiChar
}
pub fn select_left_nibble(&mut self) {
self.sel = CursorSelects::LeftNibble;
}
pub fn select_right_nibble(&mut self) {
self.sel = CursorSelects::RightNibble;
}
pub fn select_ascii(&mut self) {
self.sel = CursorSelects::AsciiChar;
}
pub fn pos(&self) -> usize {
self.pos
}
pub fn set_pos(&mut self, new_position: usize) {
self.pos = new_position;
}
pub fn trim_to_max_minus_one(&mut self, upperlimit: usize) {
let last_element: usize = upperlimit.saturating_sub(1);
if self.pos > last_element {
self.pos = last_element;
}
}
pub fn trim_to_min(&mut self, lowerlimit: usize) {
if self.pos < lowerlimit {
self.pos = lowerlimit;
}
}
pub fn add(&mut self, addend: usize, upperlimit: usize) {
self.pos += addend;
self.trim_to_max_minus_one(upperlimit);
}
pub fn sub(&mut self, subtrahend: usize, lowerlimit: usize) {
self.pos = self.pos.saturating_sub(subtrahend);
self.trim_to_min(lowerlimit);
}
pub fn calculate_pos_on_line(&self, columns: usize) -> usize {
self.pos % columns
}
pub fn calculate_start_of_line(&self, columns: usize) -> usize {
self.pos - self.calculate_pos_on_line(columns)
}
pub fn calculate_end_of_line(&self, columns: usize) -> usize {
self.calculate_start_of_line(columns) + (columns - 1)
}
pub fn jump_to_start_of_line(&mut self, columns: usize) {
self.pos = self.calculate_start_of_line(columns);
}
pub fn jump_to_end_of_line(&mut self, columns: usize, upperlimit: usize) {
self.pos = self.calculate_end_of_line(columns);
self.trim_to_max_minus_one(upperlimit);
}
pub fn jump_to_line(&mut self, line: usize, columns: usize, upperlimit: usize) {
self.set_pos(line * columns);
self.trim_to_max_minus_one(upperlimit);
}
pub fn jump_to_pos_on_line(
&mut self,
line: usize,
pos_on_line: usize,
columns: usize,
upperlimit: usize,
) {
self.set_pos(line * columns + pos_on_line);
self.trim_to_max_minus_one(upperlimit);
}
}
#[test]
fn cursor_default() {
let cursor = Cursor::default();
assert_eq!(cursor.pos, 0);
assert_eq!(cursor.sel, CursorSelects::LeftNibble);
}
#[test]
fn cursor_jump_to_start_of_line() {
const COLS: usize = 16;
let buf: Vec<u8> = (0..20).collect();
let mut cursor = Cursor::default();
cursor.pos = buf.len().saturating_sub(1);
assert_eq!(cursor.pos, 19);
cursor.jump_to_start_of_line(COLS);
assert_eq!(cursor.pos, 16);
cursor.sub(1, 0);
cursor.jump_to_start_of_line(COLS);
assert_eq!(cursor.pos, 0);
}
#[test]
fn cursor_jump_to_end_of_line() {
const COLS: usize = 16;
let buf: Vec<u8> = (0..20).collect();
let mut cursor = Cursor::default();
cursor.jump_to_end_of_line(COLS, buf.len());
assert_eq!(cursor.pos, 15);
cursor.add(1, buf.len());
println!("{:?}", buf.len());
cursor.jump_to_end_of_line(COLS, buf.len());
assert_eq!(cursor.pos, 19);
}