Skip to content

Commit

Permalink
[tui] Clean up confusing caret types - raw and scroll adjusted
Browse files Browse the repository at this point in the history
Caret position can be of two kinds:
- Raw
- Scroll adjusted

Make this explicity using the type system and provide conversions
between the two.

Introduce new concrete types for:
- Pos
  - row
  - col
- Dim
  - width
  - height
- Use them in the codebase instead of ChUnit.
- Use ChUnit as the "inner" type of these new concrete types.
  • Loading branch information
nazmulidris committed Feb 3, 2025
1 parent 09ccbe1 commit 2278bf6
Show file tree
Hide file tree
Showing 20 changed files with 197 additions and 212 deletions.
24 changes: 0 additions & 24 deletions .vscode/bookmarks.json

This file was deleted.

1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
"mworld",
"nanos",
"neovim",
"nextest",
"Nodesource",
"notcurses",
"nushell",
Expand Down
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion core/src/stack_alloc_types/sizes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use smallvec::SmallVec;
/// Intermediate struct used to insert a grapheme cluster segment into an existing unicode
/// string. When this gets larger than `DEFAULT_STRING_SIZE`, it will be
/// [smallvec::SmallVec::spilled] on the heap.
pub type VecStrBuffer<'a> = SmallVec<[&'a str; VEC_STR_BUFFER_CAPACITY]>;
pub type VecArrayStr<'a> = SmallVec<[&'a str; VEC_STR_BUFFER_CAPACITY]>;
const VEC_STR_BUFFER_CAPACITY: usize = 16;

/// Stack allocated string storage for small strings. When this gets larger than
Expand Down
52 changes: 52 additions & 0 deletions core/src/tui_core/dimens/ch_unit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ pub struct ChUnit {

impl ChUnit {
pub fn new(value: ChUnitPrimitiveType) -> Self { Self { value } }

pub fn reset(&mut self) { self.value = 0; }
}

/// ```rust
Expand Down Expand Up @@ -291,3 +293,53 @@ pub mod convert_from_other_types_to_ch {
}
}
}

#[cfg(test)]
mod tests {
use crate::{ChUnit, assert_eq2, ch, u16, usize};

#[test]
fn test_from_whatever_into_ch() {
let ch_1: ChUnit = ch(1);
assert_eq2!(*ch_1, 1);

let ch_2: ChUnit = ch(1) + ch(1);
assert_eq2!(*ch_2, 2);

let ch_3: ChUnit = ch(1) - ch(1);
assert_eq2!(*ch_3, 0);

let ch_4: ChUnit = ch(0) - ch(1);
assert_eq2!(*ch_4, 0);
}

#[test]
fn test_from_ch_into_usize() {
let usize_1: usize = usize(ch(1));
assert_eq2!(usize_1, 1);

let usize_2: usize = usize(ch(1) + ch(1));
assert_eq2!(usize_2, 2);

let usize_3: usize = usize(ch(1) - ch(1));
assert_eq2!(usize_3, 0);

let usize_4: usize = usize(ch(0) - ch(1));
assert_eq2!(usize_4, 0);
}

#[test]
fn test_from_ch_into_u16() {
let u16_1: u16 = u16(ch(1));
assert_eq2!(u16_1, 1);

let u16_2: u16 = u16(ch(1) + ch(1));
assert_eq2!(u16_2, 2);

let u16_3: u16 = u16(ch(1) - ch(1));
assert_eq2!(u16_3, 0);

let u16_4: u16 = u16(ch(0) - ch(1));
assert_eq2!(u16_4, 0);
}
}
1 change: 0 additions & 1 deletion core/src/tui_core/dimens/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,4 @@ pub use requested_size::*;
pub use size::*;

// Tests.
mod test_ch_unit;
mod test_dimens;
9 changes: 2 additions & 7 deletions core/src/tui_core/dimens/position.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

use std::{fmt::{self, Debug},
ops::{Add, AddAssign, Mul}};
use std::{fmt::{Debug, Formatter, Result},
ops::{Add, AddAssign, Mul, Sub}};

use crate::{ChUnit, Size, ch};

Expand Down Expand Up @@ -144,8 +143,6 @@ impl Position {
}

pub mod position_math_ops {
use std::ops::Sub;

use super::*;

impl AddAssign<ChUnit> for Position {
Expand Down Expand Up @@ -216,8 +213,6 @@ pub mod convert_position_to_other_type {
}

pub mod position_debug_formatter {
use fmt::{Formatter, Result};

use super::*;

impl Debug for Position {
Expand Down
66 changes: 0 additions & 66 deletions core/src/tui_core/dimens/test_ch_unit.rs

This file was deleted.

5 changes: 3 additions & 2 deletions core/src/tui_core/graphemes/access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,10 @@ impl UnicodeString {
/// Uses [SelectionRange] to calculate width and simply calls
/// [clip_to_width](Self::clip_to_width).
pub fn clip_to_range(&self, range: SelectionRange) -> &str {
// BUG: [ ] introduce scroll adjusted type
let SelectionRange {
start_display_col_index,
end_display_col_index,
start_display_col_index_scroll_adjusted: start_display_col_index,
end_display_col_index_scroll_adjusted: end_display_col_index,
} = range;
let max_display_col_count = end_display_col_index - start_display_col_index;
self.clip_to_width(start_display_col_index, max_display_col_count)
Expand Down
12 changes: 6 additions & 6 deletions core/src/tui_core/graphemes/change.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* limitations under the License.
*/

use crate::{ChUnit, StringStorage, UnicodeString, VecStrBuffer, ch, join};
use crate::{ChUnit, StringStorage, UnicodeString, VecArrayStr, ch, join};

impl UnicodeString {
/// Inserts the given `chunk` in the correct position of the `string`, and returns a
Expand All @@ -29,7 +29,7 @@ impl UnicodeString {
chunk: &str,
) -> (StringStorage, ChUnit) {
// Create an array-vec of &str from self.vec_segment, using self.iter().
let mut acc = VecStrBuffer::with_capacity(self.len() + 1);
let mut acc = VecArrayStr::with_capacity(self.len() + 1);
acc.extend(self.iter().map(|seg| seg.get_str(&self.string)));

match self.logical_index_at_display_col_index(display_col) {
Expand Down Expand Up @@ -66,7 +66,7 @@ impl UnicodeString {
let split_logical_index = self.logical_index_at_display_col_index(display_col)?;
let max_logical_index = self.len();

let mut vec_left = VecStrBuffer::with_capacity(self.len());
let mut vec_left = VecArrayStr::with_capacity(self.len());
let mut str_left_unicode_width = ch(0);
{
for logical_idx in 0..split_logical_index {
Expand All @@ -78,7 +78,7 @@ impl UnicodeString {
}

let skip_split_logical_index = split_logical_index + 1; // Drop one segment.
let mut vec_right = VecStrBuffer::with_capacity(self.len());
let mut vec_right = VecArrayStr::with_capacity(self.len());
let mut str_right_unicode_width = ch(0);
{
for logical_idx in skip_split_logical_index..max_logical_index {
Expand All @@ -104,7 +104,7 @@ impl UnicodeString {
let split_logical_index = self.logical_index_at_display_col_index(display_col)?;
let max_logical_index = self.len();

let mut vec_left = VecStrBuffer::with_capacity(self.len());
let mut vec_left = VecArrayStr::with_capacity(self.len());
let mut str_left_unicode_width = ch(0);
{
for logical_idx in 0..split_logical_index {
Expand All @@ -114,7 +114,7 @@ impl UnicodeString {
}
}

let mut vec_right = VecStrBuffer::with_capacity(self.len());
let mut vec_right = VecArrayStr::with_capacity(self.len());
let mut str_right_unicode_width = ch(0);
{
for logical_idx in split_logical_index..max_logical_index {
Expand Down
29 changes: 16 additions & 13 deletions core/src/tui_core/graphemes/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,12 @@ use crate::{ChUnit, Position};
/// - `▓▓` = `😃`
/// - [clip_to_range](crate::UnicodeString::clip_to_range): "e😃"
#[derive(Default, Clone, PartialEq, Copy, size_of::SizeOf)]
// BUG: [ ] introduce scroll adjusted type
pub struct SelectionRange {
pub start_display_col_index: ChUnit,
pub end_display_col_index: ChUnit,
/// This is not "raw", this is "scroll adjusted".
pub start_display_col_index_scroll_adjusted: ChUnit,
/// This is not "raw", this is "scroll adjusted".
pub end_display_col_index_scroll_adjusted: ChUnit,
}

#[derive(Clone, PartialEq, Copy, Debug)]
Expand All @@ -54,7 +57,7 @@ impl SelectionRange {
&self,
scroll_offset: Position,
) -> ScrollOffsetColLocationInRange {
if self.start_display_col_index >= scroll_offset.col_index {
if self.start_display_col_index_scroll_adjusted >= scroll_offset.col_index {
ScrollOffsetColLocationInRange::Underflow
} else {
ScrollOffsetColLocationInRange::Overflow
Expand Down Expand Up @@ -163,9 +166,9 @@ impl SelectionRange {
/// ```
/// - [UnicodeString::clip_to_range](crate::UnicodeString::clip_to_range): "ell"
pub fn locate_column(&self, caret_display_col_index: ChUnit) -> CaretLocationInRange {
if caret_display_col_index < self.start_display_col_index {
if caret_display_col_index < self.start_display_col_index_scroll_adjusted {
CaretLocationInRange::Underflow
} else if caret_display_col_index >= self.end_display_col_index {
} else if caret_display_col_index >= self.end_display_col_index_scroll_adjusted {
CaretLocationInRange::Overflow
} else {
CaretLocationInRange::Contained
Expand All @@ -174,8 +177,8 @@ impl SelectionRange {

pub fn new(start_display_col_index: ChUnit, end_display_col_index: ChUnit) -> Self {
Self {
start_display_col_index,
end_display_col_index,
start_display_col_index_scroll_adjusted: start_display_col_index,
end_display_col_index_scroll_adjusted: end_display_col_index,
}
}

Expand All @@ -189,7 +192,7 @@ impl SelectionRange {
/// ```
pub fn grow_end_by(&self, amount: ChUnit) -> Self {
let mut copy = *self;
copy.end_display_col_index += amount;
copy.end_display_col_index_scroll_adjusted += amount;
copy
}

Expand All @@ -203,7 +206,7 @@ impl SelectionRange {
/// ```
pub fn shrink_end_by(&self, amount: ChUnit) -> Self {
let mut copy = *self;
copy.end_display_col_index -= amount;
copy.end_display_col_index_scroll_adjusted -= amount;
copy
}

Expand All @@ -217,7 +220,7 @@ impl SelectionRange {
/// ```
pub fn grow_start_by(&self, amount: ChUnit) -> Self {
let mut copy = *self;
copy.start_display_col_index -= amount;
copy.start_display_col_index_scroll_adjusted -= amount;
copy
}

Expand All @@ -231,7 +234,7 @@ impl SelectionRange {
/// ```
pub fn shrink_start_by(&self, amount: ChUnit) -> Self {
let mut copy = *self;
copy.start_display_col_index += amount;
copy.start_display_col_index_scroll_adjusted += amount;
copy
}
}
Expand All @@ -244,8 +247,8 @@ mod range_impl_debug_format {
write!(
f,
"[start_display_col_index: {start:?}, end_display_col_index: {end:?}]",
start = self.start_display_col_index,
end = self.end_display_col_index
start = self.start_display_col_index_scroll_adjusted,
end = self.end_display_col_index_scroll_adjusted
)
}
}
Expand Down
Loading

0 comments on commit 2278bf6

Please sign in to comment.