1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// Copyright (c) 2025 R3BL LLC. Licensed under Apache License, Version 2.0.
use crate::{CaretScrAdj, EditorBuffer, handle_selection_multiline_caret_movement,
handle_selection_multiline_caret_movement_hit_top_or_bottom_of_document,
handle_selection_single_line_caret_movement};
use std::cmp::Ordering;
#[derive(Clone, Copy, Debug)]
pub enum SelectMode {
Enabled,
Disabled,
}
impl SelectMode {
#[must_use]
pub fn get_caret_scr_adj(&self, buffer: &EditorBuffer) -> Option<CaretScrAdj> {
match self {
SelectMode::Enabled => Some(buffer.get_caret_scr_adj()),
SelectMode::Disabled => None,
}
}
/// Manage the selection based on the movement of the caret:
/// - <kbd>Shift + Left</kbd>
/// - <kbd>Shift + Right</kbd>
/// - <kbd>Shift + Home</kbd>
/// - <kbd>Shift + End</kbd>
///
/// # Arguments
/// - `editor_buffer` - The buffer to update. This holds the selection map.
/// - `maybe_previous_caret_display_pos` - The previous position of the caret.
/// - This maybe [None] if [`SelectMode`] is [`SelectMode::Disabled`].
/// - This has to be [Some] if [`SelectMode::Enabled`].
/// - `maybe_current_caret_display_pos` - The current position of the caret.
/// - This maybe [None] if [`SelectMode`] is [`SelectMode::Disabled`].
/// - This has to be [Some] if [`SelectMode::Enabled`].
pub fn handle_selection_single_line_caret_movement(
&self,
editor_buffer: &mut EditorBuffer,
maybe_prev_caret: Option<CaretScrAdj>,
maybe_curr_caret: Option<CaretScrAdj>,
) -> Option<()> {
match self {
// Cancel the selection. We don't care about the caret positions (they maybe
// None or not).
SelectMode::Disabled => editor_buffer.clear_selection(),
// Create or update the selection w/ the caret positions (which can't be
// None).
SelectMode::Enabled => {
let prev = maybe_prev_caret?;
let curr = maybe_curr_caret?;
if prev.row_index != curr.row_index {
return None;
}
handle_selection_single_line_caret_movement(
editor_buffer,
prev, // `prev.row_index` is same as `current.row_index`.
curr,
);
}
}
None
}
pub fn update_selection_based_on_caret_movement_in_multiple_lines(
&self,
buffer: &mut EditorBuffer,
maybe_prev_caret: Option<CaretScrAdj>,
maybe_curr_caret: Option<CaretScrAdj>,
) -> Option<()> {
match self {
// Cancel the selection. We don't care about the caret positions (they maybe
// None or not).
SelectMode::Disabled => buffer.clear_selection(),
// Create or update the selection w/ the caret positions (which can't be
// None).
SelectMode::Enabled => {
let prev = maybe_prev_caret?;
let curr = maybe_curr_caret?;
match prev.row_index.cmp(&curr.row_index) {
Ordering::Equal => handle_selection_multiline_caret_movement_hit_top_or_bottom_of_document(
buffer,
prev,
curr,
),
_ => handle_selection_multiline_caret_movement(
buffer,
prev,
curr,
),
}
}
}
None
}
}
#[derive(Clone, PartialEq, Copy, Debug)]
pub enum DeleteSelectionWith {
Backspace,
Delete,
AnyKey,
}