1use crate::prelude::*;
7use crate::EditAction;
8
9pub trait Resolve<T, R> {
11 fn resolve(&self, t: &T) -> R;
13}
14
15#[derive(Clone, Debug, Eq, PartialEq)]
17pub struct EditContext {
18 pub(crate) operation: EditAction,
19 pub(crate) mark: Option<Mark>,
20 pub(crate) count: Option<usize>,
21 pub(crate) typed: Option<Char>,
22
23 pub(crate) cursor_end: CursorEnd,
24 pub(crate) target_shape: Option<TargetShape>,
25 pub(crate) insert_style: Option<InsertStyle>,
26 pub(crate) last_column: bool,
27 pub(crate) register: Option<Register>,
28 pub(crate) register_append: bool,
29 pub(crate) search_regex_dir: MoveDir1D,
30 pub(crate) search_char: Option<(MoveDir1D, bool, Char)>,
31 pub(crate) replace_char: Option<Char>,
32 pub(crate) search_incremental: bool,
33}
34
35impl Default for EditContext {
36 fn default() -> Self {
37 Self {
38 operation: EditAction::Motion,
39 mark: None,
40 count: None,
41 typed: None,
42
43 cursor_end: CursorEnd::Auto,
44 target_shape: None,
45 insert_style: None,
46 last_column: true,
47 register: None,
48 register_append: false,
49 search_regex_dir: MoveDir1D::Next,
50 search_char: None,
51 replace_char: None,
52 search_incremental: false,
53 }
54 }
55}
56
57impl EditContext {
58 pub fn get_cursor_end(&self) -> CursorEnd {
60 self.cursor_end
61 }
62
63 pub fn get_target_shape(&self) -> Option<TargetShape> {
65 self.target_shape
66 }
67
68 pub fn get_insert_style(&self) -> Option<InsertStyle> {
70 self.insert_style
71 }
72
73 pub fn get_last_column(&self) -> bool {
75 self.last_column
76 }
77
78 pub fn get_count(&self) -> Option<usize> {
80 self.count
81 }
82
83 pub fn get_register(&self) -> Option<Register> {
85 self.register.clone()
86 }
87
88 pub fn get_register_append(&self) -> bool {
90 self.register_append
91 }
92
93 pub fn get_search_regex_dir(&self) -> MoveDir1D {
95 self.search_regex_dir
96 }
97
98 pub fn get_search_char(&self) -> Option<(MoveDir1D, bool, Char)> {
101 self.search_char.clone()
102 }
103
104 pub fn get_replace_char(&self) -> Option<Char> {
106 self.replace_char.clone()
107 }
108
109 pub fn is_search_incremental(&self) -> bool {
111 self.search_incremental
112 }
113}
114
115impl Resolve<Count, usize> for EditContext {
116 fn resolve(&self, count: &Count) -> usize {
117 match count {
118 Count::Contextual => self.count.unwrap_or(1),
119 Count::MinusOne => self.count.unwrap_or(0).saturating_sub(1),
120 Count::Exact(n) => *n,
121 }
122 }
123}
124
125impl Resolve<Specifier<Char>, Option<Char>> for EditContext {
126 fn resolve(&self, c: &Specifier<Char>) -> Option<Char> {
127 match c {
128 Specifier::Contextual => self.typed.clone(),
129 Specifier::Exact(c) => Some(c.clone()),
130 }
131 }
132}
133
134impl Resolve<Specifier<Mark>, Mark> for EditContext {
135 fn resolve(&self, mark: &Specifier<Mark>) -> Mark {
136 match mark {
137 Specifier::Contextual => self.mark.unwrap_or(Mark::LastJump),
138 Specifier::Exact(m) => *m,
139 }
140 }
141}
142
143impl Resolve<Specifier<EditAction>, EditAction> for EditContext {
144 fn resolve(&self, mark: &Specifier<EditAction>) -> EditAction {
145 match mark {
146 Specifier::Contextual => self.operation.clone(),
147 Specifier::Exact(a) => a.clone(),
148 }
149 }
150}
151
152#[derive(Default)]
154pub struct EditContextBuilder(EditContext);
155
156impl EditContextBuilder {
157 pub fn build(self) -> EditContext {
159 self.0
160 }
161
162 pub fn cursor_end(mut self, v: CursorEnd) -> Self {
166 self.0.cursor_end = v;
167 self
168 }
169
170 pub fn target_shape(mut self, v: Option<TargetShape>) -> Self {
174 self.0.target_shape = v;
175 self
176 }
177
178 pub fn insert_style(mut self, v: Option<InsertStyle>) -> Self {
182 self.0.insert_style = v;
183 self
184 }
185
186 pub fn last_column(mut self, v: bool) -> Self {
190 self.0.last_column = v;
191 self
192 }
193
194 pub fn register(mut self, v: Option<Register>) -> Self {
198 self.0.register = v;
199 self
200 }
201
202 pub fn register_append(mut self, v: bool) -> Self {
207 self.0.register_append = v;
208 self
209 }
210
211 pub fn search_regex_dir(mut self, v: MoveDir1D) -> Self {
215 self.0.search_regex_dir = v;
216 self
217 }
218
219 pub fn search_char(mut self, v: Option<(MoveDir1D, bool, Char)>) -> Self {
223 self.0.search_char = v;
224 self
225 }
226
227 pub fn replace_char(mut self, v: Option<Char>) -> Self {
231 self.0.replace_char = v;
232 self
233 }
234
235 pub fn search_incremental(mut self, v: bool) -> Self {
239 self.0.search_incremental = v;
240 self
241 }
242
243 pub fn mark(mut self, mark: Option<Mark>) -> Self {
247 self.0.mark = mark;
248 self
249 }
250
251 pub fn typed_char(mut self, ch: Option<Char>) -> Self {
255 self.0.typed = ch;
256 self
257 }
258
259 pub fn operation(mut self, op: EditAction) -> Self {
263 self.0.operation = op;
264 self
265 }
266
267 pub fn count(mut self, n: Option<usize>) -> Self {
271 self.0.count = n;
272 self
273 }
274}
275
276impl From<EditContext> for EditContextBuilder {
277 fn from(ctx: EditContext) -> Self {
278 EditContextBuilder(ctx)
279 }
280}