use std::{
cmp::min,
fmt::{Display, Formatter},
};
#[derive(Debug, Clone, Copy)]
pub struct View<'a, T> {
contents: &'a [T],
_index: usize,
}
impl Display for View<'_, char> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
for ch in self.contents {
ch.fmt(f)?;
}
Ok(())
}
}
impl<'a, T> View<'a, T> {
pub fn index(&self) -> usize {
self._index
}
pub fn as_slice(&self) -> &'a [T] {
self.contents
}
}
#[derive(Debug, Clone, Copy)]
pub struct Cursor {
index: usize,
offset: usize,
width: usize,
}
impl Cursor {
pub fn new(width: usize) -> Self {
Self {
index: 0,
offset: 0,
width,
}
}
pub fn idx(&self) -> usize {
self.index
}
pub fn view_padded<'a, T>(&self, left: usize, right: usize, buffer: &'a [T]) -> View<'a, T> {
let view_left = self.offset.saturating_sub(left);
let view_right = min(view_left + left + self.width + right, buffer.len());
View {
contents: &buffer[view_left..view_right],
_index: self.index - view_left,
}
}
#[inline]
pub fn view<'a, T>(&self, target: &'a [T]) -> View<'a, T> {
self.view_padded(0, 0, target)
}
pub fn set_index(&mut self, index: usize) {
self.index = index;
self.reset();
}
pub fn set_width(&mut self, width: usize) {
self.width = width;
self.reset();
}
fn reset(&mut self) {
if self.index < self.offset {
self.offset = self.index;
} else if self.index >= self.offset + self.width {
self.offset = self.index - self.width;
}
}
}