use crate::tui::layout::TuiPane;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) struct TextPosition {
pub(crate) byte: usize,
pub(crate) row: usize,
pub(crate) col: usize,
}
impl TextPosition {
pub(crate) fn new(byte: usize, row: usize, col: usize) -> Self {
Self { byte, row, col }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) struct ActiveSelection {
pub(crate) pane: TuiPane,
pub(crate) anchor: TextPosition,
pub(crate) current: TextPosition,
}
impl ActiveSelection {
pub(crate) fn new(pane: TuiPane, anchor: TextPosition) -> Self {
Self {
pane,
anchor,
current: anchor,
}
}
pub(crate) fn set_current(&mut self, current: TextPosition) {
self.current = current;
}
pub(crate) fn byte_range(&self) -> Option<(usize, usize)> {
let start = self.anchor.byte.min(self.current.byte);
let end = self.anchor.byte.max(self.current.byte);
(start < end).then_some((start, end))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn reversed_selection_normalizes_range() {
let mut selection = ActiveSelection::new(TuiPane::Prompt, TextPosition::new(8, 0, 8));
selection.set_current(TextPosition::new(2, 0, 2));
assert_eq!(selection.byte_range(), Some((2, 8)));
}
#[test]
fn empty_selection_has_no_range() {
let selection = ActiveSelection::new(TuiPane::Transcript, TextPosition::new(2, 0, 2));
assert_eq!(selection.byte_range(), None);
}
}