@@ -1121,5 +1121,88 @@ public void ViInsertModeMoveCursor()
11211121 _ . RightArrow , // 'RightArrow' again does nothing, but doesn't crash
11221122 "c" ) ) ;
11231123 }
1124+
1125+ [ SkippableFact ]
1126+ public void ViDefect1281_1 ( )
1127+ {
1128+ TestSetup ( KeyMode . Vi ) ;
1129+
1130+ Test ( "bcd" , Keys (
1131+ "abcdabcd" , _ . Escape ,
1132+
1133+ // return to the [B]eginning of the word,
1134+ // then [c]hange text un[t]il just before the [2]nd [b] character
1135+ // this leaves the cursor at the current position (0) but erases
1136+ // the "abcda" text portion, / switches to edit mode and
1137+ // positions the cursor just before the "bcd" text portion.
1138+
1139+ "Bc2tb" ,
1140+
1141+ // going back to normal mode again without having modified the buffer further
1142+ // even though the [c] command started an edit group, going back to normal
1143+ // mode closes the pending edit group.
1144+
1145+ _ . Escape , CheckThat ( ( ) => AssertCursorLeftIs ( 0 ) ) ,
1146+
1147+ // attempt to [c]hange text un[t]il just before the [2]nd [b] character again
1148+ // because the [b] character only appears once further down in the buffer
1149+ // relative to where the cursor position is – currently set to 0 - the command
1150+ // fails. Therefore, we are still in normal mode.
1151+ //
1152+ // as the command failed, the current edit group is now correctly closed.
1153+
1154+ "c2tb" , CheckThat ( ( ) => AssertLineIs ( "bcd" ) ) ,
1155+
1156+ // attempt to [c]hange text un[t]il just before the [2]nd [b] character a third time.
1157+ // this exercises a code path where starting a edit group while another
1158+ // pending edit group was previously started crashed PSRL.
1159+ //
1160+ // this should no longer crash as any started pending group is now properly closed if
1161+ // the command fails
1162+ "c2tb"
1163+ ) ) ;
1164+ }
1165+
1166+ [ SkippableFact ]
1167+ public void ViDefect1281_2 ( )
1168+ {
1169+ TestSetup ( KeyMode . Vi ) ;
1170+
1171+ Test ( "abc" , Keys (
1172+ "abc" , _ . Escape ,
1173+
1174+ // 'cff' triggers `ViReplaceToChar` to delete until the character 'f'. But 'abc' doesn't
1175+ // have the letter 'f', so the started edit group should be ended and cursor is not moved.
1176+ "cff" ,
1177+ CheckThat ( ( ) => AssertCursorLeftIs ( 2 ) ) ,
1178+
1179+ // the subsequent 'cc' calls `ViReplaceLine` to replace the current line with 'i', which
1180+ // starts a new edit group.
1181+ "ccip" ,
1182+ CheckThat ( ( ) => AssertLineIs ( "ip" ) ) ,
1183+
1184+ // now we undo the 'cci' step, and accept the current command line, which should be 'abc'.
1185+ _ . Escape , "u"
1186+ ) ) ;
1187+ }
1188+
1189+ [ SkippableFact ]
1190+ public void ViDefect1281_3 ( )
1191+ {
1192+ TestSetup ( KeyMode . Vi ) ;
1193+
1194+ Test ( "bcd" , Keys (
1195+ "bcd" , _ . Escape , _ . LeftArrow , _ . LeftArrow ,
1196+
1197+ // 'a' triggers `ViInsertWithAppend` and we append 'iii' after 'b'.
1198+ "aiii" ,
1199+ CheckThat ( ( ) => AssertCursorLeftIs ( 4 ) ) ,
1200+ CheckThat ( ( ) => AssertLineIs ( "biiicd" ) ) ,
1201+
1202+ // now we undo the 'aiii' step, and accept the current command line,
1203+ // which should be 'bcd'.
1204+ _ . Escape , "u"
1205+ ) ) ;
1206+ }
11241207 }
11251208}
0 commit comments