@@ -23,6 +23,8 @@ actions!(
2323 HelixInsert ,
2424 /// Appends at the end of the selection.
2525 HelixAppend ,
26+ /// Goes to the location of the last modification.
27+ HelixGotoLastModification ,
2628 ]
2729) ;
2830
@@ -31,6 +33,7 @@ pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
3133 Vim :: action ( editor, cx, Vim :: helix_insert) ;
3234 Vim :: action ( editor, cx, Vim :: helix_append) ;
3335 Vim :: action ( editor, cx, Vim :: helix_yank) ;
36+ Vim :: action ( editor, cx, Vim :: helix_goto_last_modification) ;
3437}
3538
3639impl Vim {
@@ -430,6 +433,15 @@ impl Vim {
430433 } ) ;
431434 self . switch_mode ( Mode :: HelixNormal , true , window, cx) ;
432435 }
436+
437+ pub fn helix_goto_last_modification (
438+ & mut self ,
439+ _: & HelixGotoLastModification ,
440+ window : & mut Window ,
441+ cx : & mut Context < Self > ,
442+ ) {
443+ self . jump ( "." . into ( ) , false , false , window, cx) ;
444+ }
433445}
434446
435447#[ cfg( test) ]
@@ -441,6 +453,7 @@ mod test {
441453 #[ gpui:: test]
442454 async fn test_word_motions ( cx : & mut gpui:: TestAppContext ) {
443455 let mut cx = VimTestContext :: new ( cx, true ) . await ;
456+ cx. enable_helix ( ) ;
444457 // «
445458 // ˇ
446459 // »
@@ -502,6 +515,7 @@ mod test {
502515 #[ gpui:: test]
503516 async fn test_delete ( cx : & mut gpui:: TestAppContext ) {
504517 let mut cx = VimTestContext :: new ( cx, true ) . await ;
518+ cx. enable_helix ( ) ;
505519
506520 // test delete a selection
507521 cx. set_state (
@@ -582,6 +596,7 @@ mod test {
582596 #[ gpui:: test]
583597 async fn test_f_and_t ( cx : & mut gpui:: TestAppContext ) {
584598 let mut cx = VimTestContext :: new ( cx, true ) . await ;
599+ cx. enable_helix ( ) ;
585600
586601 cx. set_state (
587602 indoc ! { "
@@ -635,6 +650,7 @@ mod test {
635650 #[ gpui:: test]
636651 async fn test_newline_char ( cx : & mut gpui:: TestAppContext ) {
637652 let mut cx = VimTestContext :: new ( cx, true ) . await ;
653+ cx. enable_helix ( ) ;
638654
639655 cx. set_state ( "aa«\n ˇ»bb cc" , Mode :: HelixNormal ) ;
640656
@@ -652,6 +668,7 @@ mod test {
652668 #[ gpui:: test]
653669 async fn test_insert_selected ( cx : & mut gpui:: TestAppContext ) {
654670 let mut cx = VimTestContext :: new ( cx, true ) . await ;
671+ cx. enable_helix ( ) ;
655672 cx. set_state (
656673 indoc ! { "
657674 «The ˇ»quick brown
@@ -674,6 +691,7 @@ mod test {
674691 #[ gpui:: test]
675692 async fn test_append ( cx : & mut gpui:: TestAppContext ) {
676693 let mut cx = VimTestContext :: new ( cx, true ) . await ;
694+ cx. enable_helix ( ) ;
677695 // test from the end of the selection
678696 cx. set_state (
679697 indoc ! { "
@@ -716,6 +734,7 @@ mod test {
716734 #[ gpui:: test]
717735 async fn test_replace ( cx : & mut gpui:: TestAppContext ) {
718736 let mut cx = VimTestContext :: new ( cx, true ) . await ;
737+ cx. enable_helix ( ) ;
719738
720739 // No selection (single character)
721740 cx. set_state ( "ˇaa" , Mode :: HelixNormal ) ;
@@ -763,4 +782,72 @@ mod test {
763782 cx. shared_clipboard ( ) . assert_eq ( "worl" ) ;
764783 cx. assert_state ( "hello «worlˇ»d" , Mode :: HelixNormal ) ;
765784 }
785+ #[ gpui:: test]
786+ async fn test_shift_r_paste ( cx : & mut gpui:: TestAppContext ) {
787+ let mut cx = VimTestContext :: new ( cx, true ) . await ;
788+ cx. enable_helix ( ) ;
789+
790+ // First copy some text to clipboard
791+ cx. set_state ( "«hello worldˇ»" , Mode :: HelixNormal ) ;
792+ cx. simulate_keystrokes ( "y" ) ;
793+
794+ // Test paste with shift-r on single cursor
795+ cx. set_state ( "foo ˇbar" , Mode :: HelixNormal ) ;
796+ cx. simulate_keystrokes ( "shift-r" ) ;
797+
798+ cx. assert_state ( "foo hello worldˇbar" , Mode :: HelixNormal ) ;
799+
800+ // Test paste with shift-r on selection
801+ cx. set_state ( "foo «barˇ» baz" , Mode :: HelixNormal ) ;
802+ cx. simulate_keystrokes ( "shift-r" ) ;
803+
804+ cx. assert_state ( "foo hello worldˇ baz" , Mode :: HelixNormal ) ;
805+ }
806+
807+ #[ gpui:: test]
808+ async fn test_insert_mode_stickiness ( cx : & mut gpui:: TestAppContext ) {
809+ let mut cx = VimTestContext :: new ( cx, true ) . await ;
810+ cx. enable_helix ( ) ;
811+
812+ // Make a modification at a specific location
813+ cx. set_state ( "ˇhello" , Mode :: HelixNormal ) ;
814+ assert_eq ! ( cx. mode( ) , Mode :: HelixNormal ) ;
815+ cx. simulate_keystrokes ( "i" ) ;
816+ assert_eq ! ( cx. mode( ) , Mode :: Insert ) ;
817+ cx. simulate_keystrokes ( "escape" ) ;
818+ assert_eq ! ( cx. mode( ) , Mode :: HelixNormal ) ;
819+ }
820+
821+ #[ gpui:: test]
822+ async fn test_goto_last_modification ( cx : & mut gpui:: TestAppContext ) {
823+ let mut cx = VimTestContext :: new ( cx, true ) . await ;
824+ cx. enable_helix ( ) ;
825+
826+ // Make a modification at a specific location
827+ cx. set_state ( "line one\n line ˇtwo\n line three" , Mode :: HelixNormal ) ;
828+ cx. assert_state ( "line one\n line ˇtwo\n line three" , Mode :: HelixNormal ) ;
829+ cx. simulate_keystrokes ( "i" ) ;
830+ cx. simulate_keystrokes ( "escape" ) ;
831+ cx. simulate_keystrokes ( "i" ) ;
832+ cx. simulate_keystrokes ( "m o d i f i e d space" ) ;
833+ cx. simulate_keystrokes ( "escape" ) ;
834+
835+ // TODO: this fails, because state is no longer helix
836+ cx. assert_state (
837+ "line one\n line modified ˇtwo\n line three" ,
838+ Mode :: HelixNormal ,
839+ ) ;
840+
841+ // Move cursor away from the modification
842+ cx. simulate_keystrokes ( "up" ) ;
843+
844+ // Use "g ." to go back to last modification
845+ cx. simulate_keystrokes ( "g ." ) ;
846+
847+ // Verify we're back at the modification location and still in HelixNormal mode
848+ cx. assert_state (
849+ "line one\n line modifiedˇ two\n line three" ,
850+ Mode :: HelixNormal ,
851+ ) ;
852+ }
766853}
0 commit comments