diff --git a/.vscode/settings.json b/.vscode/settings.json index 524c0d7a..f3a5a8c5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -99,6 +99,7 @@ "mworld", "nanos", "neovim", + "newtype", "nextest", "Nodesource", "notcurses", diff --git a/tui/src/tui/editor/editor_buffer/buffer_selection_support.rs b/tui/src/tui/editor/editor_buffer/buffer_selection_support.rs index b784339b..ee9d81f7 100644 --- a/tui/src/tui/editor/editor_buffer/buffer_selection_support.rs +++ b/tui/src/tui/editor/editor_buffer/buffer_selection_support.rs @@ -55,7 +55,7 @@ pub fn handle_selection_single_line_caret_movement( let buffer_mut = buffer.get_mut(width(0) + height(0)); - buffer_mut.sel_list.insert( + buffer_mut.inner.sel_list.insert( row_index, new_range, SelectionRange::caret_movement_direction_left_right(previous, current), @@ -120,7 +120,7 @@ pub fn handle_selection_single_line_caret_movement( let new_range = range.shrink_end_by(width(*delta)); let buffer_mut = buffer.get_mut(width(0) + height(0)); - buffer_mut.sel_list.insert( + buffer_mut.inner.sel_list.insert( row_index, new_range, SelectionRange::caret_movement_direction_left_right(previous, current), @@ -137,7 +137,7 @@ pub fn handle_selection_single_line_caret_movement( let new_range = range.grow_start_by(width(*delta)); let buffer_mut = buffer.get_mut(width(0) + height(0)); - buffer_mut.sel_list.insert( + buffer_mut.inner.sel_list.insert( row_index, new_range, SelectionRange::caret_movement_direction_left_right(previous, current), @@ -154,7 +154,7 @@ pub fn handle_selection_single_line_caret_movement( let new_range = range.grow_end_by(width(*delta)); let buffer_mut = buffer.get_mut(width(0) + height(0)); - buffer_mut.sel_list.insert( + buffer_mut.inner.sel_list.insert( row_index, new_range, SelectionRange::caret_movement_direction_left_right(previous, current), @@ -172,7 +172,7 @@ pub fn handle_selection_single_line_caret_movement( let new_range = range.shrink_start_by(width(*delta)); let buffer_mut = buffer.get_mut(width(0) + height(0)); - buffer_mut.sel_list.insert( + buffer_mut.inner.sel_list.insert( row_index, new_range, SelectionRange::caret_movement_direction_left_right(previous, current), @@ -189,7 +189,7 @@ pub fn handle_selection_single_line_caret_movement( if let Some(range) = buffer.get_selection_list().get(row_index) { if range.start_disp_col_idx_scr_adj == range.end_disp_col_idx_scr_adj { let buffer_mut = buffer.get_mut(width(0) + height(0)); - buffer_mut.sel_list.remove( + buffer_mut.inner.sel_list.remove( row_index, SelectionRange::caret_movement_direction_left_right(previous, current), ); @@ -301,7 +301,7 @@ pub fn handle_selection_multiline_caret_movement_hit_top_or_bottom_of_document( /* 3: row_index */ d = format!("row_index: {:?}", row_index).green().on_dark_grey(), /* 4: selection_map */ - e = format!("{:?}", buffer_mut.sel_list) + e = format!("{:?}", buffer_mut.inner.sel_list) .magenta() .on_dark_grey(), ); @@ -314,12 +314,12 @@ pub fn handle_selection_multiline_caret_movement_hit_top_or_bottom_of_document( match curr.col_index.cmp(&prev.col_index) { cmp::Ordering::Less => { - match buffer_mut.sel_list.get(row_index) { + match buffer_mut.inner.sel_list.get(row_index) { // Extend range to left (caret moved up and hit the top). Some(range) => { let start = col(0); let end = range.end_disp_col_idx_scr_adj; - buffer_mut.sel_list.insert( + buffer_mut.inner.sel_list.insert( row_index, SelectionRange { start_disp_col_idx_scr_adj: start, @@ -332,7 +332,7 @@ pub fn handle_selection_multiline_caret_movement_hit_top_or_bottom_of_document( None => { let start = col(0); let end = prev.col_index; - buffer_mut.sel_list.insert( + buffer_mut.inner.sel_list.insert( row_index, SelectionRange { start_disp_col_idx_scr_adj: start, @@ -344,17 +344,17 @@ pub fn handle_selection_multiline_caret_movement_hit_top_or_bottom_of_document( } } cmp::Ordering::Greater => { - match buffer_mut.sel_list.get(row_index) { + match buffer_mut.inner.sel_list.get(row_index) { // Extend range to right (caret moved down and hit bottom). Some(range) => { - if let Some(line_us) = buffer_mut.lines.get(usize(row_index)) { + if let Some(line_us) = buffer_mut.inner.lines.get(usize(row_index)) { let start = range.start_disp_col_idx_scr_adj; // For selection, go one col index past the end of the line, // since selection range is not inclusive of the end index. let end = caret_scroll_index::col_index_for_width( line_us.display_width, ); - buffer_mut.sel_list.insert( + buffer_mut.inner.sel_list.insert( row_index, SelectionRange { start_disp_col_idx_scr_adj: start, @@ -368,7 +368,7 @@ pub fn handle_selection_multiline_caret_movement_hit_top_or_bottom_of_document( None => { let start = prev.col_index; let end = curr.col_index; - buffer_mut.sel_list.insert( + buffer_mut.inner.sel_list.insert( row_index, SelectionRange { start_disp_col_idx_scr_adj: start, @@ -650,12 +650,12 @@ mod multiline_select_helpers { }; let buffer_mut = buffer.get_mut(width(0) + height(0)); - buffer_mut.sel_list.insert( + buffer_mut.inner.sel_list.insert( first.row_index, first_row_range, caret_vertical_movement_direction, ); - buffer_mut.sel_list.insert( + buffer_mut.inner.sel_list.insert( last.row_index, last_row_range, caret_vertical_movement_direction, @@ -681,7 +681,7 @@ mod multiline_select_helpers { let buffer_mut = buffer.get_mut(width(0) + height(0)); // Extend the existing range (in selection map) for the first row to end of line. - if let Some(first_row_range) = buffer_mut.sel_list.get(first.row_index) { + if let Some(first_row_range) = buffer_mut.inner.sel_list.get(first.row_index) { let start_col = first_row_range.start_disp_col_idx_scr_adj; // Go one col index past the end of the width, since selection range is not // inclusive of end index. @@ -690,7 +690,7 @@ mod multiline_select_helpers { start_disp_col_idx_scr_adj: start_col, end_disp_col_idx_scr_adj: end_col, }; - buffer_mut.sel_list.insert( + buffer_mut.inner.sel_list.insert( first.row_index, new_first_row_range, caret_vertical_movement_direction, @@ -703,7 +703,7 @@ mod multiline_select_helpers { let end_col = last.col_index; (start_col, end_col).into() }; - buffer_mut.sel_list.insert( + buffer_mut.inner.sel_list.insert( last.row_index, last_row_range, caret_vertical_movement_direction, @@ -729,7 +729,7 @@ mod multiline_select_helpers { let buffer_mut = buffer.get_mut(width(0) + height(0)); // FIRST ROW. - if let Some(first_row_range) = buffer_mut.sel_list.get(first.row_index) { + if let Some(first_row_range) = buffer_mut.inner.sel_list.get(first.row_index) { // Extend the existing range (in selection map) for the first row to end of line. let updated_first_row_range = SelectionRange { start_disp_col_idx_scr_adj: first_row_range.start_disp_col_idx_scr_adj, @@ -738,7 +738,7 @@ mod multiline_select_helpers { // not inclusive of end index. caret_scroll_index::col_index_for_width(first_line_width), }; - buffer_mut.sel_list.insert( + buffer_mut.inner.sel_list.insert( first.row_index, updated_first_row_range, caret_vertical_movement_direction, @@ -756,7 +756,7 @@ mod multiline_select_helpers { ) .into() }; - buffer_mut.sel_list.insert( + buffer_mut.inner.sel_list.insert( first.row_index, new_first_row_range, caret_vertical_movement_direction, @@ -764,7 +764,7 @@ mod multiline_select_helpers { } // LAST ROW. - if let Some(last_row_range) = buffer_mut.sel_list.get(last.row_index) { + if let Some(last_row_range) = buffer_mut.inner.sel_list.get(last.row_index) { // Extend the existing range (in selection map) for the last row to start of line. let start_col = col(0); let end_col = last_row_range.end_disp_col_idx_scr_adj; @@ -772,7 +772,7 @@ mod multiline_select_helpers { start_disp_col_idx_scr_adj: start_col, end_disp_col_idx_scr_adj: end_col, }; - buffer_mut.sel_list.insert( + buffer_mut.inner.sel_list.insert( last.row_index, updated_last_row_range, caret_vertical_movement_direction, @@ -784,7 +784,7 @@ mod multiline_select_helpers { let end_col = last.col_index; (start_col, end_col).into() }; - buffer_mut.sel_list.insert( + buffer_mut.inner.sel_list.insert( last.row_index, new_last_row_range, caret_vertical_movement_direction, @@ -808,24 +808,26 @@ mod multiline_select_helpers { let buffer_mut = buffer.get_mut(width(0) + height(0)); // Drop the existing range (in selection map) for the last row. - if buffer_mut.sel_list.get(last.row_index).is_some() { + if buffer_mut.inner.sel_list.get(last.row_index).is_some() { buffer_mut + .inner .sel_list .remove(last.row_index, caret_vertical_movement_direction); } // Change the existing range (in selection map) for the first row. - if let Some(first_row_range) = buffer_mut.sel_list.get(first.row_index) { + if let Some(first_row_range) = buffer_mut.inner.sel_list.get(first.row_index) { let lhs = first_row_range.start_disp_col_idx_scr_adj; let rhs = first.col_index; match lhs.cmp(&rhs) { cmp::Ordering::Equal => { buffer_mut + .inner .sel_list .remove(first.row_index, caret_vertical_movement_direction); } cmp::Ordering::Less | cmp::Ordering::Greater => { - buffer_mut.sel_list.insert( + buffer_mut.inner.sel_list.insert( first.row_index, SelectionRange { start_disp_col_idx_scr_adj: lhs.min(rhs), @@ -854,23 +856,25 @@ mod multiline_select_helpers { let buffer_mut = buffer.get_mut(width(0) + height(0)); // Drop the existing range (in selection map) for the first row. - if buffer_mut.sel_list.get(first.row_index).is_some() { + if buffer_mut.inner.sel_list.get(first.row_index).is_some() { buffer_mut + .inner .sel_list .remove(first.row_index, caret_vertical_movement_direction); } // Change the existing range (in selection map) for the last row. - if let Some(last_row_range) = buffer_mut.sel_list.get(last.row_index) { + if let Some(last_row_range) = buffer_mut.inner.sel_list.get(last.row_index) { let lhs = last.col_index; let rhs = last_row_range.end_disp_col_idx_scr_adj; let row_index = last.row_index; match lhs.cmp(&rhs) { cmp::Ordering::Equal => buffer_mut + .inner .sel_list .remove(row_index, caret_vertical_movement_direction), cmp::Ordering::Greater | cmp::Ordering::Less => { - buffer_mut.sel_list.insert( + buffer_mut.inner.sel_list.insert( row_index, SelectionRange { start_disp_col_idx_scr_adj: rhs.min(lhs), diff --git a/tui/src/tui/editor/editor_buffer/buffer_struct.rs b/tui/src/tui/editor/editor_buffer/buffer_struct.rs index a3a9c6a2..86405e63 100644 --- a/tui/src/tui/editor/editor_buffer/buffer_struct.rs +++ b/tui/src/tui/editor/editor_buffer/buffer_struct.rs @@ -33,6 +33,7 @@ use r3bl_core::{call_if_true, CharStorage, ColWidth, Dim, + RowHeight, RowIndex, ScrOfs, Size, @@ -47,7 +48,7 @@ use smallvec::{smallvec, SmallVec}; use super::SelectionList; use crate::{caret_locate, editor_engine::engine_public_api, - validate_buffer_mut::EditorBufferMut, + validate_buffer_mut::{EditorBufferMutNoDrop, EditorBufferMutWithDrop}, EditorEngine, HasFocus, RenderArgs, @@ -82,9 +83,10 @@ use crate::{caret_locate, /// All the fields in this struct are private. In order to access them you have to use the /// accessor associated functions. To mutate them, you have to use the /// [get_mut](EditorBuffer::get_mut) method, which returns a struct of mutable references -/// to the fields. This struct [EditorBufferMut] implements the [Drop] trait, which allows -/// for validation [crate::validate_buffer_mut::perform_validation_checks_after_mutation] -/// operations to be applied post mutation. +/// to the fields. This struct [crate::EditorBufferMut] implements the [Drop] trait, which +/// allows for validation +/// [crate::validate_buffer_mut::perform_validation_checks_after_mutation] operations to +/// be applied post mutation. /// /// # Different kinds of caret positions /// @@ -367,7 +369,7 @@ pub mod content { } /// Get line display with at caret's scroll adjusted row index. Use this when you - /// don't have access to this struct. Eg: in [EditorBufferMut]. + /// don't have access to this struct. Eg: in [crate::EditorBufferMut]. pub fn impl_get_line_display_width_at_caret_scr_adj( caret_raw: CaretRaw, scr_ofs: ScrOfs, @@ -506,8 +508,6 @@ pub mod content { } pub mod access_and_mutate { - use r3bl_core::RowHeight; - use super::*; impl EditorBuffer { @@ -615,16 +615,16 @@ pub mod access_and_mutate { /// This makes it easy to determine what code mutates this struct, since it is /// necessary to validate things after mutation quite a bit in editor_ops.rs. /// - /// [EditorBufferMut] implements the [Drop] trait, which ensures that any + /// [crate::EditorBufferMut] implements the [Drop] trait, which ensures that any /// validation changes are applied after making changes to the [EditorBuffer]. - pub fn get_mut(&mut self, vp: Dim) -> EditorBufferMut<'_> { - EditorBufferMut { - lines: &mut self.content.lines, - caret_raw: &mut self.content.caret_raw, - scr_ofs: &mut self.content.scr_ofs, - sel_list: &mut self.content.sel_list, + pub fn get_mut(&mut self, vp: Dim) -> EditorBufferMutWithDrop<'_> { + EditorBufferMutWithDrop::new( + &mut self.content.lines, + &mut self.content.caret_raw, + &mut self.content.scr_ofs, + &mut self.content.sel_list, vp, - } + ) } /// This is a special case of [EditorBuffer::get_mut] where the [Drop] trait is @@ -632,13 +632,13 @@ pub mod access_and_mutate { /// don't want to run validation checks after mutation, which happens when the /// window is resized using [mod@crate::validate_scroll_on_resize]. pub fn get_mut_no_drop(&mut self, vp: Dim) -> EditorBufferMutNoDrop<'_> { - EditorBufferMutNoDrop { - lines: &mut self.content.lines, - caret_raw: &mut self.content.caret_raw, - scr_ofs: &mut self.content.scr_ofs, - sel_list: &mut self.content.sel_list, + EditorBufferMutNoDrop::new( + &mut self.content.lines, + &mut self.content.caret_raw, + &mut self.content.scr_ofs, + &mut self.content.sel_list, vp, - } + ) } pub fn has_selection(&self) -> bool { !self.content.sel_list.is_empty() } @@ -649,20 +649,6 @@ pub mod access_and_mutate { } } -pub struct EditorBufferMutNoDrop<'a> { - pub lines: &'a mut VecEditorContentLines, - pub caret_raw: &'a mut CaretRaw, - pub scr_ofs: &'a mut ScrOfs, - pub sel_list: &'a mut SelectionList, - /// - Viewport width is optional because it's only needed for caret validation. - /// And you can get it from [crate::EditorEngine]. You can pass `0` if you don't have - /// it. - /// - Viewport height is optional because it's only needed for caret validation. - /// And you can get it from [crate::EditorEngine]. You can pass `0` if you don't have - /// it. - pub vp: Dim, -} - pub mod history { use super::*; diff --git a/tui/src/tui/editor/editor_engine/caret_mut.rs b/tui/src/tui/editor/editor_engine/caret_mut.rs index acd659a5..897817d2 100644 --- a/tui/src/tui/editor/editor_engine/caret_mut.rs +++ b/tui/src/tui/editor/editor_engine/caret_mut.rs @@ -49,8 +49,8 @@ pub fn up(buffer: &mut EditorBuffer, engine: &mut EditorEngine, sel_mod: SelectM let buffer_mut = buffer.get_mut(engine.viewport()); scroll_editor_content::reset_caret_col( - buffer_mut.caret_raw, - buffer_mut.scr_ofs, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, ); } } @@ -64,8 +64,8 @@ pub fn up(buffer: &mut EditorBuffer, engine: &mut EditorEngine, sel_mod: SelectM let buffer_mut = buffer.get_mut(engine.viewport()); scroll_editor_content::dec_caret_row( - buffer_mut.caret_raw, - buffer_mut.scr_ofs, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, ); } @@ -133,9 +133,9 @@ pub fn down(buffer: &mut EditorBuffer, engine: &mut EditorEngine, sel_mod: Selec let buffer_mut = buffer.get_mut(engine.viewport()); scroll_editor_content::inc_caret_row( - buffer_mut.caret_raw, - buffer_mut.scr_ofs, - buffer_mut.vp.row_height, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, + buffer_mut.inner.vp.row_height, ); } @@ -213,8 +213,8 @@ pub fn to_start_of_line( let buffer_mut = buffer.get_mut(engine.viewport()); scroll_editor_content::reset_caret_col( - buffer_mut.caret_raw, - buffer_mut.scr_ofs, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, ); } } @@ -255,9 +255,9 @@ pub fn to_end_of_line( // - `line_display_width` which is the same as: // - `line_display_width.convert_to_col_index() /*-1*/ + 1` caret_scroll_index::col_index_for_width(line_display_width), - buffer_mut.caret_raw, - buffer_mut.scr_ofs, - buffer_mut.vp.col_width, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, + buffer_mut.inner.vp.col_width, line_display_width, ); } @@ -380,11 +380,11 @@ pub fn right(buffer: &mut EditorBuffer, engine: &mut EditorEngine, sel_mod: Sele let buffer_mut = buffer.get_mut(engine.viewport()); scroll_editor_content::inc_caret_col_by( - buffer_mut.caret_raw, - buffer_mut.scr_ofs, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, jump_by_col_width, max_display_width, - buffer_mut.vp.col_width, + buffer_mut.inner.vp.col_width, ); } @@ -395,8 +395,8 @@ pub fn right(buffer: &mut EditorBuffer, engine: &mut EditorEngine, sel_mod: Sele let buffer_mut = buffer.get_mut(engine.viewport()); scroll_editor_content::dec_caret_col_by( - buffer_mut.caret_raw, - buffer_mut.scr_ofs, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, move_left_by_amt, ); } @@ -408,11 +408,11 @@ pub fn right(buffer: &mut EditorBuffer, engine: &mut EditorEngine, sel_mod: Sele let buffer_mut = buffer.get_mut(engine.viewport()); scroll_editor_content::inc_caret_col_by( - buffer_mut.caret_raw, - buffer_mut.scr_ofs, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, unicode_width_at_caret, max_display_width, - buffer_mut.vp.col_width, + buffer_mut.inner.vp.col_width, ); } } @@ -425,11 +425,11 @@ pub fn right(buffer: &mut EditorBuffer, engine: &mut EditorEngine, sel_mod: Sele let buffer_mut = buffer.get_mut(engine.viewport()); scroll_editor_content::inc_caret_col_by( - buffer_mut.caret_raw, - buffer_mut.scr_ofs, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, unicode_width_at_caret, max_display_width, - buffer_mut.vp.col_width, + buffer_mut.inner.vp.col_width, ); } } @@ -449,14 +449,14 @@ pub fn right(buffer: &mut EditorBuffer, engine: &mut EditorEngine, sel_mod: Sele let buffer_mut = buffer.get_mut(engine.viewport()); scroll_editor_content::inc_caret_row( - buffer_mut.caret_raw, - buffer_mut.scr_ofs, - buffer_mut.vp.row_height, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, + buffer_mut.inner.vp.row_height, ); scroll_editor_content::reset_caret_col( - buffer_mut.caret_raw, - buffer_mut.scr_ofs, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, ); } } @@ -486,8 +486,8 @@ pub fn left( let buffer_mut = buffer.get_mut(editor.viewport()); scroll_editor_content::dec_caret_row( - buffer_mut.caret_raw, - buffer_mut.scr_ofs, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, ); } @@ -502,8 +502,8 @@ pub fn left( let buffer_mut = buffer.get_mut(editor.viewport()); scroll_editor_content::dec_caret_col_by( - buffer_mut.caret_raw, - buffer_mut.scr_ofs, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, seg_slice.seg_display_width, ); } @@ -516,8 +516,8 @@ pub fn left( let buffer_mut = buffer.get_mut(editor.viewport()); scroll_editor_content::dec_caret_col_by( - buffer_mut.caret_raw, - buffer_mut.scr_ofs, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, seg_slice.seg_display_width, ); } diff --git a/tui/src/tui/editor/editor_engine/content_mut.rs b/tui/src/tui/editor/editor_engine/content_mut.rs index 6617608c..f0a41ff2 100644 --- a/tui/src/tui/editor/editor_engine/content_mut.rs +++ b/tui/src/tui/editor/editor_engine/content_mut.rs @@ -68,7 +68,7 @@ pub fn insert_new_line_at_caret(args: EditorArgsMut<'_>) { // validation performed. { let buffer_mut = buffer.get_mut(engine.viewport()); - buffer_mut.lines.push("".unicode_string()); + buffer_mut.inner.lines.push("".unicode_string()); } return; } @@ -107,17 +107,18 @@ pub fn insert_new_line_at_caret(args: EditorArgsMut<'_>) { let buffer_mut = buffer.get_mut(engine.viewport()); let new_row_index = scroll_editor_content::inc_caret_row( - buffer_mut.caret_raw, - buffer_mut.scr_ofs, - buffer_mut.vp.row_height, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, + buffer_mut.inner.vp.row_height, ); scroll_editor_content::reset_caret_col( - buffer_mut.caret_raw, - buffer_mut.scr_ofs, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, ); buffer_mut + .inner .lines .insert(new_row_index.as_usize(), "".unicode_string()); } @@ -132,8 +133,9 @@ pub fn insert_new_line_at_caret(args: EditorArgsMut<'_>) { { let buffer_mut = buffer.get_mut(engine.viewport()); let cur_row_index = - (*buffer_mut.caret_raw + *buffer_mut.scr_ofs).row_index; + (*buffer_mut.inner.caret_raw + *buffer_mut.inner.scr_ofs).row_index; buffer_mut + .inner .lines .insert(cur_row_index.as_usize(), "".unicode_string()); } @@ -143,9 +145,9 @@ pub fn insert_new_line_at_caret(args: EditorArgsMut<'_>) { { let buffer_mut = buffer.get_mut(engine.viewport()); scroll_editor_content::inc_caret_row( - buffer_mut.caret_raw, - buffer_mut.scr_ofs, - buffer_mut.vp.row_height, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, + buffer_mut.inner.vp.row_height, ); } } @@ -167,23 +169,24 @@ pub fn insert_new_line_at_caret(args: EditorArgsMut<'_>) { let buffer_mut = buffer.get_mut(engine.viewport()); let _ = std::mem::replace( - &mut buffer_mut.lines[row_index], + &mut buffer_mut.inner.lines[row_index], left_string.unicode_string(), ); buffer_mut + .inner .lines .insert(row_index + 1, right_string.unicode_string()); scroll_editor_content::inc_caret_row( - buffer_mut.caret_raw, - buffer_mut.scr_ofs, - buffer_mut.vp.row_height, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, + buffer_mut.inner.vp.row_height, ); scroll_editor_content::reset_caret_col( - buffer_mut.caret_raw, - buffer_mut.scr_ofs, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, ); } } @@ -230,9 +233,10 @@ pub fn delete_at_caret( // validation performed. { let buffer_mut = buffer.get_mut(engine.viewport()); - let row_index = (*buffer_mut.caret_raw + *buffer_mut.scr_ofs).row_index; + let row_index = + (*buffer_mut.inner.caret_raw + *buffer_mut.inner.scr_ofs).row_index; let _ = std::mem::replace( - &mut buffer_mut.lines[row_index.as_usize()], + &mut buffer_mut.inner.lines[row_index.as_usize()], new_line_content.unicode_string(), ); } @@ -261,12 +265,13 @@ pub fn delete_at_caret( // validation performed. { let buffer_mut = buffer.get_mut(engine.viewport()); - let row_index = (*buffer_mut.caret_raw + *buffer_mut.scr_ofs).row_index; + let row_index = + (*buffer_mut.inner.caret_raw + *buffer_mut.inner.scr_ofs).row_index; let _ = std::mem::replace( - &mut buffer_mut.lines[row_index.as_usize()], + &mut buffer_mut.inner.lines[row_index.as_usize()], new_line_content.unicode_string(), ); - buffer_mut.lines.remove(row_index.as_usize() + 1); + buffer_mut.inner.lines.remove(row_index.as_usize() + 1); } None @@ -320,20 +325,20 @@ pub fn backspace_at_caret( { let buffer_mut = buffer.get_mut(engine.viewport()); let cur_row_index = - (*buffer_mut.caret_raw + *buffer_mut.scr_ofs).row_index; + (*buffer_mut.inner.caret_raw + *buffer_mut.inner.scr_ofs).row_index; let _ = std::mem::replace( - &mut buffer_mut.lines[cur_row_index.as_usize()], + &mut buffer_mut.inner.lines[cur_row_index.as_usize()], new_line_content.unicode_string(), ); let new_line_content_display_width = - buffer_mut.lines[cur_row_index.as_usize()].display_width; + buffer_mut.inner.lines[cur_row_index.as_usize()].display_width; scroll_editor_content::set_caret_col_to( delete_at_this_display_col, - buffer_mut.caret_raw, - buffer_mut.scr_ofs, - buffer_mut.vp.col_width, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, + buffer_mut.inner.vp.col_width, new_line_content_display_width, ); } @@ -371,24 +376,25 @@ pub fn backspace_at_caret( let buffer_mut = buffer.get_mut(engine.viewport()); let prev_row_index = - (*buffer_mut.caret_raw + *buffer_mut.scr_ofs).row_index - row(1); + (*buffer_mut.inner.caret_raw + *buffer_mut.inner.scr_ofs).row_index + - row(1); let cur_row_index = - (*buffer_mut.caret_raw + *buffer_mut.scr_ofs).row_index; + (*buffer_mut.inner.caret_raw + *buffer_mut.inner.scr_ofs).row_index; let _ = std::mem::replace( - &mut buffer_mut.lines[prev_row_index.as_usize()], + &mut buffer_mut.inner.lines[prev_row_index.as_usize()], new_line_content.unicode_string(), ); let new_line_content_display_width = - buffer_mut.lines[prev_row_index.as_usize()].display_width; + buffer_mut.inner.lines[prev_row_index.as_usize()].display_width; - buffer_mut.lines.remove(cur_row_index.as_usize()); + buffer_mut.inner.lines.remove(cur_row_index.as_usize()); scroll_editor_content::dec_caret_row( - buffer_mut.caret_raw, - buffer_mut.scr_ofs, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, ); scroll_editor_content::set_caret_col_to( @@ -396,9 +402,9 @@ pub fn backspace_at_caret( // - `prev_line_display_width` which is the same as: // - `prev_line_display_width.convert_to_col_index() /*-1*/ + 1` caret_scroll_index::col_index_for_width(prev_line_display_width), - buffer_mut.caret_raw, - buffer_mut.scr_ofs, - buffer_mut.vp.col_width, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, + buffer_mut.inner.vp.col_width, new_line_content_display_width, ); } @@ -476,7 +482,7 @@ pub fn delete_selected( for row_index in map_lines_to_replace.keys() { let new_line_content = map_lines_to_replace[row_index].clone(); let _ = std::mem::replace( - &mut buffer_mut.lines[row_index.as_usize()], + &mut buffer_mut.inner.lines[row_index.as_usize()], new_line_content.unicode_string(), ); } @@ -484,7 +490,7 @@ pub fn delete_selected( // Remove lines in inverse order, in order to preserve the validity of indices. vec_row_indices_to_remove.reverse(); for row_index in vec_row_indices_to_remove { - buffer_mut.lines.remove(row_index.as_usize()); + buffer_mut.inner.lines.remove(row_index.as_usize()); } // Restore caret position to start of selection range. @@ -493,9 +499,9 @@ pub fn delete_selected( if let Some(new_caret_scr_adj) = maybe_new_caret { // Convert scroll adjusted caret to raw caret by applying scroll offset. - // Equivalent to: `let caret_raw = *new_caret_scr_adj - *buffer_mut.scr_ofs;` - let caret_raw = new_caret_scr_adj + *buffer_mut.scr_ofs; - *buffer_mut.caret_raw = caret_raw; + // Equivalent to: `let caret_raw = *new_caret_scr_adj - *buffer_mut.inner.scr_ofs;` + let caret_raw = new_caret_scr_adj + *buffer_mut.inner.scr_ofs; + *buffer_mut.inner.caret_raw = caret_raw; } } @@ -523,20 +529,20 @@ fn insert_into_existing_line( // Replace existing line w/ new line. let _ = std::mem::replace( - &mut buffer_mut.lines[row_index.as_usize()], + &mut buffer_mut.inner.lines[row_index.as_usize()], new_line_content.unicode_string(), ); let new_line_content_display_width = - buffer_mut.lines[row_index.as_usize()].display_width; + buffer_mut.inner.lines[row_index.as_usize()].display_width; // Update caret position. scroll_editor_content::inc_caret_col_by( - buffer_mut.caret_raw, - buffer_mut.scr_ofs, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, chunk_display_width, new_line_content_display_width, - buffer_mut.vp.col_width, + buffer_mut.inner.vp.col_width, ); } @@ -557,7 +563,7 @@ fn fill_in_missing_lines_up_to_row(args: EditorArgsMut<'_>, row_index: RowIndex) // performed. { let buffer_mut = buffer.get_mut(engine.viewport()); - buffer_mut.lines.push("".unicode_string()); + buffer_mut.inner.lines.push("".unicode_string()); } } } @@ -581,19 +587,22 @@ fn insert_chunk_into_new_line( // Actually add the character to the correct line. let new_content = chunk.unicode_string(); - let _ = std::mem::replace(&mut buffer_mut.lines[row_index_scr_adj], new_content); + let _ = std::mem::replace( + &mut buffer_mut.inner.lines[row_index_scr_adj], + new_content, + ); - let line_content = &buffer_mut.lines[row_index_scr_adj]; + let line_content = &buffer_mut.inner.lines[row_index_scr_adj]; let line_content_display_width = line_content.display_width; let col_amt = UnicodeString::str_display_width(chunk); // Update caret position. scroll_editor_content::inc_caret_col_by( - buffer_mut.caret_raw, - buffer_mut.scr_ofs, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, col_amt, line_content_display_width, - buffer_mut.vp.col_width, + buffer_mut.inner.vp.col_width, ); } diff --git a/tui/src/tui/editor/editor_engine/mod.rs b/tui/src/tui/editor/editor_engine/mod.rs index 0ee52ed5..b0dfa821 100644 --- a/tui/src/tui/editor/editor_engine/mod.rs +++ b/tui/src/tui/editor/editor_engine/mod.rs @@ -31,4 +31,5 @@ pub mod validate_scroll_on_resize; pub use engine_public_api::*; pub use engine_struct::*; pub use select_mode::*; +pub use validate_buffer_mut::*; pub use validate_scroll_on_resize::*; diff --git a/tui/src/tui/editor/editor_engine/scroll_editor_content.rs b/tui/src/tui/editor/editor_engine/scroll_editor_content.rs index 5a2e0aa8..0a90b304 100644 --- a/tui/src/tui/editor/editor_engine/scroll_editor_content.rs +++ b/tui/src/tui/editor/editor_engine/scroll_editor_content.rs @@ -372,9 +372,9 @@ pub fn change_caret_row_by( while diff > row(0) { inc_caret_row( - buffer_mut.caret_raw, - buffer_mut.scr_ofs, - buffer_mut.vp.row_height, + buffer_mut.inner.caret_raw, + buffer_mut.inner.scr_ofs, + buffer_mut.inner.vp.row_height, ); diff -= row(1); } @@ -389,11 +389,11 @@ pub fn change_caret_row_by( let buffer_mut = buffer.get_mut(engine.viewport()); while diff > height(0) { - dec_caret_row(buffer_mut.caret_raw, buffer_mut.scr_ofs); + dec_caret_row(buffer_mut.inner.caret_raw, buffer_mut.inner.scr_ofs); diff -= height(1); let row_index = { - let lhs = *buffer_mut.caret_raw; - let rhs = *buffer_mut.scr_ofs; + let lhs = *buffer_mut.inner.caret_raw; + let rhs = *buffer_mut.inner.scr_ofs; let it = lhs + rhs; it.row_index }; diff --git a/tui/src/tui/editor/editor_engine/validate_buffer_mut.rs b/tui/src/tui/editor/editor_engine/validate_buffer_mut.rs index 07af6215..097f7fbe 100644 --- a/tui/src/tui/editor/editor_engine/validate_buffer_mut.rs +++ b/tui/src/tui/editor/editor_engine/validate_buffer_mut.rs @@ -15,47 +15,136 @@ * limitations under the License. */ +//! [EditorBufferMut] holds a few important mutable references to the editor buffer. It +//! also contains some data copied from the editor engine. This is necessary when you need +//! to mutate the buffer and then run validation checks on the buffer. +//! +//! The ["newtype" +//! pattern](https://doc.rust-lang.org/rust-by-example/generics/new_types.html) is used +//! here to wrap the underlying [EditorBufferMut] struct, so that it be used in one of two +//! distinct use cases: +//! 1. Once [EditorBuffer::get_mut()] is called, the buffer is mutated and then the +//! validation checks are run. This is done by using [EditorBufferMutWithDrop]. +//! 2. If you don't want the buffer to be mutated, then you can use +//! [EditorBufferMutNoDrop] by calling [EditorBuffer::get_mut_no_drop()]. + use r3bl_core::{col, usize, width, CaretRaw, ColWidth, Dim, ScrOfs}; use super::scroll_editor_content; use crate::{editor::sizing::VecEditorContentLines, EditorBuffer, SelectionList}; -/// See the [Drop] implementation of `EditorBufferMut` which runs -/// [crate::validate_buffer_mut::perform_validation_checks_after_mutation]. -/// -/// Due to the nature of `UTF-8` and its variable width characters, where the memory size -/// is not the same as display size. Eg: `a` is 1 byte and 1 display width (unicode -/// segment width display). `😄` is 3 bytes but it's display width is 2! To ensure that -/// caret position and scroll offset positions are not in the middle of a unicode segment -/// character, we need to run the validation checks. pub struct EditorBufferMut<'a> { pub lines: &'a mut VecEditorContentLines, pub caret_raw: &'a mut CaretRaw, pub scr_ofs: &'a mut ScrOfs, pub sel_list: &'a mut SelectionList, /// - Viewport width is optional because it's only needed for caret validation. - /// And you can get it from [super::EditorEngine]. You can pass `0` if you don't have + /// And you can get it from [crate::EditorEngine]. You can pass `0` if you don't have /// it. /// - Viewport height is optional because it's only needed for caret validation. - /// And you can get it from [super::EditorEngine]. You can pass `0` if you don't have + /// And you can get it from [crate::EditorEngine]. You can pass `0` if you don't have /// it. pub vp: Dim, } -// XMARK: Clever Rust, use of Drop to perform transaction close / end. - -impl Drop for EditorBufferMut<'_> { - /// Once [crate::validate_buffer_mut::EditorBufferMut] is used to modify the buffer, - /// it needs to run the validation checks to ensure that the buffer is in a valid - /// state. This is done using - /// [crate::validate_buffer_mut::perform_validation_checks_after_mutation]. - /// - /// Due to the nature of `UTF-8` and its variable width characters, where the memory - /// size is not the same as display size. Eg: `a` is 1 byte and 1 display width - /// (unicode segment width display). `😄` is 3 bytes but it's display width is 2! To - /// ensure that caret position and scroll offset positions are not in the middle of a - /// unicode segment character, we need to run the validation checks. - fn drop(&mut self) { perform_validation_checks_after_mutation(self); } +mod editor_buffer_mut_impl_block { + use super::*; + + impl EditorBufferMut<'_> { + /// Returns the display width of the line at the caret (at it's scroll adjusted + /// row index). + pub fn get_line_display_width_at_caret_scr_adj_row_index(&self) -> ColWidth { + EditorBuffer::impl_get_line_display_width_at_caret_scr_adj( + *self.caret_raw, + *self.scr_ofs, + self.lines, + ) + } + + pub fn new<'a>( + lines: &'a mut VecEditorContentLines, + caret_raw: &'a mut CaretRaw, + scr_ofs: &'a mut ScrOfs, + sel_list: &'a mut SelectionList, + vp: Dim, + ) -> EditorBufferMut<'a> { + EditorBufferMut { + lines, + caret_raw, + scr_ofs, + sel_list, + vp, + } + } + } +} + +pub struct EditorBufferMutNoDrop<'a> { + pub inner: EditorBufferMut<'a>, +} + +mod editor_buffer_mut_no_drop_impl_block { + use super::*; + + impl EditorBufferMutNoDrop<'_> { + pub fn new<'a>( + lines: &'a mut VecEditorContentLines, + caret_raw: &'a mut CaretRaw, + scr_ofs: &'a mut ScrOfs, + sel_list: &'a mut SelectionList, + vp: Dim, + ) -> EditorBufferMutNoDrop<'a> { + EditorBufferMutNoDrop { + inner: EditorBufferMut::new(lines, caret_raw, scr_ofs, sel_list, vp), + } + } + } +} + +// XMARK: Clever Rust, use of Drop to perform transaction close / end. And also of "newtype" idiom / pattern. + +/// See the [Drop] implementation of `EditorBufferMut` which runs +/// [crate::validate_buffer_mut::perform_validation_checks_after_mutation]. +/// +/// Due to the nature of `UTF-8` and its variable width characters, where the memory size +/// is not the same as display size. Eg: `a` is 1 byte and 1 display width (unicode +/// segment width display). `😄` is 3 bytes but it's display width is 2! To ensure that +/// caret position and scroll offset positions are not in the middle of a unicode segment +/// character, we need to run the validation checks. +pub struct EditorBufferMutWithDrop<'a> { + pub inner: EditorBufferMut<'a>, +} + +mod editor_buffer_mut_with_drop_impl_block { + use super::*; + + impl EditorBufferMutWithDrop<'_> { + pub fn new<'a>( + lines: &'a mut VecEditorContentLines, + caret_raw: &'a mut CaretRaw, + scr_ofs: &'a mut ScrOfs, + sel_list: &'a mut SelectionList, + vp: Dim, + ) -> EditorBufferMutWithDrop<'a> { + EditorBufferMutWithDrop { + inner: EditorBufferMut::new(lines, caret_raw, scr_ofs, sel_list, vp), + } + } + } + + impl Drop for EditorBufferMutWithDrop<'_> { + /// Once [crate::validate_buffer_mut::EditorBufferMut] is used to modify the buffer, + /// it needs to run the validation checks to ensure that the buffer is in a valid + /// state. This is done using + /// [crate::validate_buffer_mut::perform_validation_checks_after_mutation]. + /// + /// Due to the nature of `UTF-8` and its variable width characters, where the memory + /// size is not the same as display size. Eg: `a` is 1 byte and 1 display width + /// (unicode segment width display). `😄` is 3 bytes but it's display width is 2! To + /// ensure that caret position and scroll offset positions are not in the middle of a + /// unicode segment character, we need to run the validation checks. + fn drop(&mut self) { perform_validation_checks_after_mutation(self); } + } } /// In addition to mutating the buffer, this function runs the following validations on the @@ -70,7 +159,7 @@ impl Drop for EditorBufferMut<'_> { /// The drop implementation is split out into this separate function since that is how it /// used to be written in earlier versions of the codebase, it used to be called /// `apply_change()`. Also this function can be directly linked to in documentation. -pub fn perform_validation_checks_after_mutation(arg: &mut EditorBufferMut<'_>) { +pub fn perform_validation_checks_after_mutation(arg: &mut EditorBufferMutWithDrop<'_>) { // Check caret validity. adjust_caret_col_if_not_in_middle_of_grapheme_cluster(arg); adjust_caret_col_if_not_in_bounds_of_line(arg); @@ -80,18 +169,6 @@ pub fn perform_validation_checks_after_mutation(arg: &mut EditorBufferMut<'_>) { } } -impl EditorBufferMut<'_> { - /// Returns the display width of the line at the caret (at it's scroll adjusted - /// row index). - pub fn get_line_display_width_at_caret_scr_adj_row_index(&self) -> ColWidth { - EditorBuffer::impl_get_line_display_width_at_caret_scr_adj( - *self.caret_raw, - *self.scr_ofs, - self.lines, - ) - } -} - /// ```text /// 0 4 9 1 2 2 /// 4 0 5 @@ -104,31 +181,34 @@ impl EditorBufferMut<'_> { /// row /// ``` fn adjust_caret_col_if_not_in_bounds_of_line( - editor_buffer_mut: &mut EditorBufferMut<'_>, + editor_buffer_mut: &mut EditorBufferMutWithDrop<'_>, ) { // Check right side of line. Clip scroll adjusted caret to max line width. let row_width = { - let line_display_width_at_caret_row = - editor_buffer_mut.get_line_display_width_at_caret_scr_adj_row_index(); - let scr_ofs_col_index = editor_buffer_mut.scr_ofs.col_index; + let line_display_width_at_caret_row = editor_buffer_mut + .inner + .get_line_display_width_at_caret_scr_adj_row_index(); + let scr_ofs_col_index = editor_buffer_mut.inner.scr_ofs.col_index; width(*line_display_width_at_caret_row - *scr_ofs_col_index) }; // Make sure that the col_index is within the bounds of the given line width. let new_caret_col_index = col(std::cmp::min( - *editor_buffer_mut.caret_raw.col_index, + *editor_buffer_mut.inner.caret_raw.col_index, *row_width, )); - editor_buffer_mut.caret_raw.col_index = new_caret_col_index; + editor_buffer_mut.inner.caret_raw.col_index = new_caret_col_index; } pub fn is_scroll_offset_in_middle_of_grapheme_cluster( - editor_buffer_mut: &mut EditorBufferMut<'_>, + editor_buffer_mut: &mut EditorBufferMutWithDrop<'_>, ) -> Option { - let scroll_adjusted_caret = *editor_buffer_mut.caret_raw + *editor_buffer_mut.scr_ofs; + let scroll_adjusted_caret = + *editor_buffer_mut.inner.caret_raw + *editor_buffer_mut.inner.scr_ofs; let line_at_caret = editor_buffer_mut + .inner .lines .get(usize(*scroll_adjusted_caret.row_index))?; @@ -143,7 +223,7 @@ pub fn is_scroll_offset_in_middle_of_grapheme_cluster( if let Some(segment) = line_at_caret .is_display_col_index_in_middle_of_grapheme_cluster( - editor_buffer_mut.scr_ofs.col_index, + editor_buffer_mut.inner.scr_ofs.col_index, ) { let diff = segment.unicode_width - display_width_of_str_at_caret; @@ -154,32 +234,33 @@ pub fn is_scroll_offset_in_middle_of_grapheme_cluster( } pub fn adjust_scroll_offset_because_in_middle_of_grapheme_cluster( - editor_buffer_mut: &mut EditorBufferMut<'_>, + editor_buffer_mut: &mut EditorBufferMutWithDrop<'_>, diff: ColWidth, ) -> Option<()> { - editor_buffer_mut.scr_ofs.col_index += diff; - editor_buffer_mut.caret_raw.col_index -= diff; + editor_buffer_mut.inner.scr_ofs.col_index += diff; + editor_buffer_mut.inner.caret_raw.col_index -= diff; None } /// This function is visible inside the editor_ops.rs module only. It is not meant to /// be called directly, but instead is called by the [Drop] impl of [EditorBufferMut]. pub fn adjust_caret_col_if_not_in_middle_of_grapheme_cluster( - editor_buffer_mut: &mut EditorBufferMut<'_>, + editor_buffer_mut: &mut EditorBufferMutWithDrop<'_>, ) -> Option<()> { - let caret_scr_adj = *editor_buffer_mut.caret_raw + *editor_buffer_mut.scr_ofs; + let caret_scr_adj = + *editor_buffer_mut.inner.caret_raw + *editor_buffer_mut.inner.scr_ofs; let row_index = caret_scr_adj.row_index; let col_index = caret_scr_adj.col_index; - let line = editor_buffer_mut.lines.get(row_index.as_usize())?; + let line = editor_buffer_mut.inner.lines.get(row_index.as_usize())?; // Caret is in the middle of a grapheme cluster, so jump it. let seg = line.is_display_col_index_in_middle_of_grapheme_cluster(col_index)?; scroll_editor_content::set_caret_col_to( seg.start_display_col_index + seg.unicode_width, - editor_buffer_mut.caret_raw, - editor_buffer_mut.scr_ofs, - editor_buffer_mut.vp.col_width, + editor_buffer_mut.inner.caret_raw, + editor_buffer_mut.inner.scr_ofs, + editor_buffer_mut.inner.vp.col_width, line.display_width, ); diff --git a/tui/src/tui/editor/editor_engine/validate_scroll_on_resize.rs b/tui/src/tui/editor/editor_engine/validate_scroll_on_resize.rs index b619452a..bcd2847a 100644 --- a/tui/src/tui/editor/editor_engine/validate_scroll_on_resize.rs +++ b/tui/src/tui/editor/editor_engine/validate_scroll_on_resize.rs @@ -67,7 +67,7 @@ fn validate_vertical_scroll(args: EditorArgsMut<'_>) { if caret_scr_adj_row_index.check_overflows(max_row) == BoundsStatus::Overflowed { let diff = max_row - buffer.get_caret_scr_adj().row_index; let buffer_mut = buffer.get_mut_no_drop(vp); - buffer_mut.caret_raw.row_index -= diff; + buffer_mut.inner.caret_raw.row_index -= diff; } } @@ -77,7 +77,7 @@ fn validate_vertical_scroll(args: EditorArgsMut<'_>) { if scr_ofs_row_index.check_overflows(max_row) == BoundsStatus::Overflowed { let diff = max_row - scr_ofs_row_index; let buffer_mut = buffer.get_mut_no_drop(vp); - buffer_mut.scr_ofs.row_index -= diff; + buffer_mut.inner.scr_ofs.row_index -= diff; } } @@ -111,16 +111,16 @@ fn validate_vertical_scroll(args: EditorArgsMut<'_>) { // Caret is above viewport. let row_diff = scr_ofs_row_index - caret_scr_adj_row_index; let buffer_mut = buffer.get_mut_no_drop(vp); - buffer_mut.scr_ofs.row_index -= row_diff; - buffer_mut.caret_raw.row_index += row_diff; + buffer_mut.inner.scr_ofs.row_index -= row_diff; + buffer_mut.inner.caret_raw.row_index += row_diff; } CaretLocRelativeToVp::Below => { // Caret is below viewport. let row_diff = caret_scr_adj_row_index - (scr_ofs_row_index + vp.row_height); let buffer_mut = buffer.get_mut_no_drop(vp); - buffer_mut.scr_ofs.row_index += row_diff; - buffer_mut.caret_raw.row_index -= row_diff; + buffer_mut.inner.scr_ofs.row_index += row_diff; + buffer_mut.inner.caret_raw.row_index -= row_diff; } } } @@ -181,15 +181,15 @@ fn validate_horizontal_scroll(args: EditorArgsMut<'_>) { (CaretColWithinVp::No, CaretAtSideOfVp::Left) => { // Caret is to the left of viewport. let buffer_mut = buffer.get_mut_no_drop(engine.viewport()); - *buffer_mut.scr_ofs.col_index = *caret_scr_adj_col_index; - *buffer_mut.caret_raw.col_index = ch(0); + *buffer_mut.inner.scr_ofs.col_index = *caret_scr_adj_col_index; + *buffer_mut.inner.caret_raw.col_index = ch(0); } (CaretColWithinVp::No, CaretAtSideOfVp::Right) => { // Caret is to the right of viewport. let buffer_mut = buffer.get_mut_no_drop(engine.viewport()); - *buffer_mut.scr_ofs.col_index = + *buffer_mut.inner.scr_ofs.col_index = *caret_scr_adj_col_index - *viewport_width + ch(1); - *buffer_mut.caret_raw.col_index = *viewport_width - ch(1); + *buffer_mut.inner.caret_raw.col_index = *viewport_width - ch(1); } } } @@ -207,7 +207,7 @@ mod tests { DEFAULT_SYN_HI_FILE_EXT}; // REVIEW: [ ] add test for above viewport - + // REVIEW: [ ] add test for below viewport // REVIEW: [x] add test for within viewport @@ -226,8 +226,8 @@ mod tests { { let buffer_mut = buffer.get_mut_no_drop(viewport); - *buffer_mut.caret_raw = caret_raw(row(5) + col(0)); - *buffer_mut.scr_ofs = scr_ofs(row(0) + col(0)); + *buffer_mut.inner.caret_raw = caret_raw(row(5) + col(0)); + *buffer_mut.inner.scr_ofs = scr_ofs(row(0) + col(0)); } let editor_args_mut = EditorArgsMut {