on master help sign in
(Updated) Apply motion API refinements (#6078)
c148826Gabriel Hansson
helix-term/src/commands.rs+29−39
@@ -34,7 +34,7 @@ use helix_core::{
34use helix_view::{
34use helix_view::{
35 clipboard::ClipboardType,
35 clipboard::ClipboardType,
36 document::{FormatterError, Mode, SCRATCH_BUFFER_NAME},
36 document::{FormatterError, Mode, SCRATCH_BUFFER_NAME},
37− editor::{Action, CompleteAction, Motion},
37+ editor::{Action, CompleteAction},
38 info::Info,
38 info::Info,
39 input::KeyEvent,
39 input::KeyEvent,
40 keyboard::KeyCode,
40 keyboard::KeyCode,
@@ -1099,8 +1099,7 @@ where
1099 .transform(|range| move_fn(text, range, count, behavior));
1099 .transform(|range| move_fn(text, range, count, behavior));
1100 doc.set_selection(view.id, selection);
1100 doc.set_selection(view.id, selection);
1101 };
1101 };
1102− motion(cx.editor);
1103− cx.editor.last_motion = Some(Motion(Box::new(motion)));
1102+ cx.editor.apply_motion(motion)
1104}
1103}
1105
1104
1106fn goto_prev_paragraph(cx: &mut Context) {
1105fn goto_prev_paragraph(cx: &mut Context) {
@@ -1240,10 +1239,7 @@ fn extend_next_long_word_end(cx: &mut Context) {
1240 extend_word_impl(cx, movement::move_next_long_word_end)
1239 extend_word_impl(cx, movement::move_next_long_word_end)
1241}
1240}
1242
1241
1243−fn will_find_char<F>(cx: &mut Context, search_fn: F, inclusive: bool, extend: bool)
1242+fn find_char(cx: &mut Context, direction: Direction, inclusive: bool, extend: bool) {
1244−where
1245− F: Fn(RopeSlice, char, usize, usize, bool) -> Option<usize> + 'static,
1246−{
1247 // TODO: count is reset to 1 before next key so we move it into the closure here.
1243 // TODO: count is reset to 1 before next key so we move it into the closure here.
1248 // Would be nice to carry over.
1244 // Would be nice to carry over.
1249 let count = cx.count();
1245 let count = cx.count();
@@ -1275,11 +1271,18 @@ where
1275 } => ch,
1271 } => ch,
1276 _ => return,
1272 _ => return,
1277 };
1273 };
1274+ let motion = move |editor: &mut Editor| {
1275+ match direction {
1276+ Direction::Forward => {
1277+ find_char_impl(editor, &find_next_char_impl, inclusive, extend, ch, count)
1278+ }
1279+ Direction::Backward => {
1280+ find_char_impl(editor, &find_prev_char_impl, inclusive, extend, ch, count)
1281+ }
1282+ };
1283+ };
1278
1284
1279− find_char_impl(cx.editor, &search_fn, inclusive, extend, ch, count);
1285+ cx.editor.apply_motion(motion);
1280− cx.editor.last_motion = Some(Motion(Box::new(move |editor: &mut Editor| {
1281− find_char_impl(editor, &search_fn, inclusive, extend, ch, 1);
1282− })));
1283 })
1286 })
1284}
1287}
1285
1288
@@ -1358,46 +1361,39 @@ fn find_prev_char_impl(
1358}
1361}
1359
1362
1360fn find_till_char(cx: &mut Context) {
1363fn find_till_char(cx: &mut Context) {
1361− will_find_char(cx, find_next_char_impl, false, false)
1364+ find_char(cx, Direction::Forward, false, false);
1362}
1365}
1363
1366
1364fn find_next_char(cx: &mut Context) {
1367fn find_next_char(cx: &mut Context) {
1365− will_find_char(cx, find_next_char_impl, true, false)
1368+ find_char(cx, Direction::Forward, true, false)
1366}
1369}
1367
1370
1368fn extend_till_char(cx: &mut Context) {
1371fn extend_till_char(cx: &mut Context) {
1369− will_find_char(cx, find_next_char_impl, false, true)
1372+ find_char(cx, Direction::Forward, false, true)
1370}
1373}
1371
1374
1372fn extend_next_char(cx: &mut Context) {
1375fn extend_next_char(cx: &mut Context) {
1373− will_find_char(cx, find_next_char_impl, true, true)
1376+ find_char(cx, Direction::Forward, true, true)
1374}
1377}
1375
1378
1376fn till_prev_char(cx: &mut Context) {
1379fn till_prev_char(cx: &mut Context) {
1377− will_find_char(cx, find_prev_char_impl, false, false)
1380+ find_char(cx, Direction::Backward, false, false)
1378}
1381}
1379
1382
1380fn find_prev_char(cx: &mut Context) {
1383fn find_prev_char(cx: &mut Context) {
1381− will_find_char(cx, find_prev_char_impl, true, false)
1384+ find_char(cx, Direction::Backward, true, false)
1382}
1385}
1383
1386
1384fn extend_till_prev_char(cx: &mut Context) {
1387fn extend_till_prev_char(cx: &mut Context) {
1385− will_find_char(cx, find_prev_char_impl, false, true)
1388+ find_char(cx, Direction::Backward, false, true)
1386}
1389}
1387
1390
1388fn extend_prev_char(cx: &mut Context) {
1391fn extend_prev_char(cx: &mut Context) {
1389− will_find_char(cx, find_prev_char_impl, true, true)
1392+ find_char(cx, Direction::Backward, true, true)
1390}
1393}
1391
1394
1392fn repeat_last_motion(cx: &mut Context) {
1395fn repeat_last_motion(cx: &mut Context) {
1393− let count = cx.count();
1396+ cx.editor.repeat_last_motion(cx.count())
1394− let last_motion = cx.editor.last_motion.take();
1395− if let Some(m) = &last_motion {
1396− for _ in 0..count {
1397− m.run(cx.editor);
1398− }
1399− cx.editor.last_motion = last_motion;
1400− }
1401}
1397}
1402
1398
1403fn replace(cx: &mut Context) {
1399fn replace(cx: &mut Context) {
@@ -3248,8 +3244,7 @@ fn goto_next_change_impl(cx: &mut Context, direction: Direction) {
3248
3244
3249 doc.set_selection(view.id, selection)
3245 doc.set_selection(view.id, selection)
3250 };
3246 };
3251− motion(cx.editor);
3252− cx.editor.last_motion = Some(Motion(Box::new(motion)));
3247+ cx.editor.apply_motion(motion);
3253}
3248}
3254
3249
3255/// Returns the [Range] for a [Hunk] in the given text.
3250/// Returns the [Range] for a [Hunk] in the given text.
@@ -4584,8 +4579,7 @@ fn expand_selection(cx: &mut Context) {
4584 }
4579 }
4585 }
4580 }
4586 };
4581 };
4587− motion(cx.editor);
4588− cx.editor.last_motion = Some(Motion(Box::new(motion)));
4582+ cx.editor.apply_motion(motion);
4589}
4583}
4590
4584
4591fn shrink_selection(cx: &mut Context) {
4585fn shrink_selection(cx: &mut Context) {
@@ -4609,8 +4603,7 @@ fn shrink_selection(cx: &mut Context) {
4609 doc.set_selection(view.id, selection);
4603 doc.set_selection(view.id, selection);
4610 }
4604 }
4611 };
4605 };
4612− motion(cx.editor);
4613− cx.editor.last_motion = Some(Motion(Box::new(motion)));
4606+ cx.editor.apply_motion(motion);
4614}
4607}
4615
4608
4616fn select_sibling_impl<F>(cx: &mut Context, sibling_fn: &'static F)
4609fn select_sibling_impl<F>(cx: &mut Context, sibling_fn: &'static F)
@@ -4628,8 +4621,7 @@ where
4628 doc.set_selection(view.id, selection);
4621 doc.set_selection(view.id, selection);
4629 }
4622 }
4630 };
4623 };
4631− motion(cx.editor);
4632− cx.editor.last_motion = Some(Motion(Box::new(motion)));
4624+ cx.editor.apply_motion(motion);
4633}
4625}
4634
4626
4635fn select_next_sibling(cx: &mut Context) {
4627fn select_next_sibling(cx: &mut Context) {
@@ -4912,8 +4904,7 @@ fn goto_ts_object_impl(cx: &mut Context, object: &'static str, direction: Direct
4912 editor.set_status("Syntax-tree is not available in current buffer");
4904 editor.set_status("Syntax-tree is not available in current buffer");
4913 }
4905 }
4914 };
4906 };
4915− motion(cx.editor);
4916− cx.editor.last_motion = Some(Motion(Box::new(motion)));
4907+ cx.editor.apply_motion(motion);
4917}
4908}
4918
4909
4919fn goto_next_function(cx: &mut Context) {
4910fn goto_next_function(cx: &mut Context) {
@@ -5034,8 +5025,7 @@ fn select_textobject(cx: &mut Context, objtype: textobject::TextObject) {
5034 });
5025 });
5035 doc.set_selection(view.id, selection);
5026 doc.set_selection(view.id, selection);
5036 };
5027 };
5037− textobject(cx.editor);
5038− cx.editor.last_motion = Some(Motion(Box::new(textobject)));
5028+ cx.editor.apply_motion(textobject);
5039 }
5029 }
5040 });
5030 });
5041
5031
helix-view/src/editor.rs+16−14
@@ -834,18 +834,6 @@ impl Default for SearchConfig {
834 }
834 }
835}
835}
836
836
837−pub struct Motion(pub Box<dyn Fn(&mut Editor)>);
838−impl Motion {
839− pub fn run(&self, e: &mut Editor) {
840− (self.0)(e)
841− }
842−}
843−impl std::fmt::Debug for Motion {
844− fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
845− f.write_str("motion")
846− }
847−}
848−
849#[derive(Debug, Clone, Default)]
837#[derive(Debug, Clone, Default)]
850pub struct Breakpoint {
838pub struct Breakpoint {
851 pub id: Option<usize>,
839 pub id: Option<usize>,
@@ -910,8 +898,7 @@ pub struct Editor {
910 pub auto_pairs: Option<AutoPairs>,
898 pub auto_pairs: Option<AutoPairs>,
911
899
912 pub idle_timer: Pin<Box<Sleep>>,
900 pub idle_timer: Pin<Box<Sleep>>,
913− pub last_motion: Option<Motion>,
901+ last_motion: Option<Motion>,
914−
915 pub last_completion: Option<CompleteAction>,
902 pub last_completion: Option<CompleteAction>,
916
903
917 pub exit_code: i32,
904 pub exit_code: i32,
@@ -945,6 +932,8 @@ pub struct Editor {
945 pub completion_request_handle: Option<oneshot::Sender<()>>,
932 pub completion_request_handle: Option<oneshot::Sender<()>>,
946}
933}
947
934
935+pub type Motion = Box<dyn Fn(&mut Editor)>;
936+
948pub type RedrawHandle = (Arc<Notify>, Arc<RwLock<()>>);
937pub type RedrawHandle = (Arc<Notify>, Arc<RwLock<()>>);
949
938
950#[derive(Debug)]
939#[derive(Debug)]
@@ -1051,6 +1040,19 @@ impl Editor {
1051 }
1040 }
1052 }
1041 }
1053
1042
1043+ pub fn apply_motion<F: Fn(&mut Self) + 'static>(&mut self, motion: F) {
1044+ motion(self);
1045+ self.last_motion = Some(Box::new(motion));
1046+ }
1047+
1048+ pub fn repeat_last_motion(&mut self, count: usize) {
1049+ if let Some(motion) = self.last_motion.take() {
1050+ for _ in 0..count {
1051+ motion(self);
1052+ }
1053+ self.last_motion = Some(motion);
1054+ }
1055+ }
1054 /// Current editing mode for the [`Editor`].
1056 /// Current editing mode for the [`Editor`].
1055 pub fn mode(&self) -> Mode {
1057 pub fn mode(&self) -> Mode {
1056 self.mode
1058 self.mode