diff --git a/Documents/Users/FeatureList.md b/Documents/Users/FeatureList.md index 3c7045dd..f0930cad 100644 --- a/Documents/Users/FeatureList.md +++ b/Documents/Users/FeatureList.md @@ -8,7 +8,7 @@ If you've tried a command and it really is missing, feel free to create an issue friendly contributor will pick it up eventually. ## Motion -b, B, f, F, gg, G, h, j, k, l, w, W, t, T, 0, $, ^, %, +, -, {, }, (, ), n, N, ', `, M, H, L +b, B, f, F, gg, G, h, j, k, l, w, W, t, T, 0, $, ^, %, +, -, {, }, (, ), n, N, gn, gN, ', `, M, H, L Comma and semicolon are supported. Toggle inclusive/exclusive by v is supported. @@ -92,7 +92,7 @@ v, V, Ctrl-v (v, V in visual mode to toggle or escape from visual mode is supported) -Inserting with visual block is not supported currently (Ctrl-v + Shift-I does not work.) +Inserting with visual block is also supported. ## Operation in Visual diff --git a/XVim/NSTextView+VimOperation.m b/XVim/NSTextView+VimOperation.m index 7b1b7f55..42fcf577 100644 --- a/XVim/NSTextView+VimOperation.m +++ b/XVim/NSTextView+VimOperation.m @@ -2489,6 +2489,20 @@ - (XVimRange)xvim_getMotionRange:(NSUInteger)current Motion:(XVimMotion*)motion{ end = range.location; } break; + case MOTION_SEARCH_MATCHED_FORWARD: + case MOTION_SEARCH_MATCHED_BACKWARD: + if (motion.motion == MOTION_SEARCH_MATCHED_FORWARD) { + range = [self.textStorage searchRegexForward:motion.regex from:self.insertionPoint count:motion.count option:motion.option]; + } else { + range = [self.textStorage searchRegexBackward:motion.regex from:self.insertionPoint count:motion.count option:motion.option]; + } + + // SEARCH_MATCHED uses TEXTOBJECT family code, it's more convenient but require this workaround + range.length += 1; + if (range.location != NSNotFound) { + [self xvim_setSelectedRange:NSMakeRange(range.location, 0)]; + } + break; case TEXTOBJECT_WORD: range = [self.textStorage currentWord:begin count:motion.count option:motion.option]; break; diff --git a/XVim/Test/XVimTester+Motion.m b/XVim/Test/XVimTester+Motion.m index a1caaa8e..83edb497 100644 --- a/XVim/Test/XVimTester+Motion.m +++ b/XVim/Test/XVimTester+Motion.m @@ -14,7 +14,7 @@ - (NSArray*)motion_testcases{ static NSString* text1 = @"aaa\n" // 0 (index of each WORD) @"bbb\n" // 4 @"ccc"; // 8 - + static NSString* text2 = @"a;a bbb ccc\n" // 0 4 8 @"ddd e-e fff\n" // 12 16 20 @"ggg hhh i_i\n" // 24 28 32 @@ -29,9 +29,25 @@ - (NSArray*)motion_testcases{ @"d(d e-) ddd\n" // 12 16 20 @"g[g }hh i_i\n" // 24 28 32 @" jj] kkk"; // 36 40 44 - + static NSString* text5 = @"aaa:<#bbb ccc ddd#> eee"; // 0 3 4 20 - + + + static NSString* text6 = @"a;a bbb ccc\n" // 0 4 8 + @"ddd bbb fff\n" // 12 16 20 + @"ggg bbb i_i\n" // 24 28 32 + @" jjj kkk"; // 36 40 44 + + static NSString* text7 = @"a;a ccc\n" + @"ddd bbb fff\n" + @"ggg bbb i_i\n" + @" jjj kkk"; + + static NSString* text8 = @"a;a bbb ccc\n" + @"ddd bbb fff\n" + @"ggg i_i\n" + @" jjj kkk"; + return [NSArray arrayWithObjects: // b, B XVimMakeTestCase(text2, 6, 0, @"b", text2, 4, 0), @@ -64,6 +80,10 @@ - (NSArray*)motion_testcases{ XVimMakeTestCase(text2, 44, 0, @"3G", text2, 24, 0), XVimMakeTestCase(text2, 8, 0, @"9G", text2, 40, 0), + // gn, gN + XVimMakeTestCase(text6, 0, 0, @"/bbbGdgn", text7, 4, 0), + XVimMakeTestCase(text6, 0, 0, @"/bbbGdgN", text8, 28, 0), + // ge, gE XVimMakeTestCase(text2, 9, 0, @"gE", text2, 6, 0), XVimMakeTestCase(text2, 9, 0, @"2gE", text2, 2, 0), diff --git a/XVim/XVimGMotionEvaluator.m b/XVim/XVimGMotionEvaluator.m index 49d823e6..6d567a90 100644 --- a/XVim/XVimGMotionEvaluator.m +++ b/XVim/XVimGMotionEvaluator.m @@ -51,6 +51,19 @@ - (XVimEvaluator*)k{ return nil; } +- (XVimEvaluator*)n{ + self.motion = [XVim.instance.searcher motionForRepeatSearch]; + self.motion.motion = MOTION_SEARCH_MATCHED_FORWARD; + + return nil; +} + +- (XVimEvaluator*)N{ + self.motion = [XVim.instance.searcher motionForRepeatSearch]; + self.motion.motion = MOTION_SEARCH_MATCHED_BACKWARD; + + return nil; +} - (XVimEvaluator*)searchCurrentWord:(BOOL)forward { XVimCommandLineEvaluator* eval = [self searchEvaluatorForward:forward]; NSRange r = [self.sourceView xvim_currentWord:MOTION_OPTION_NONE]; diff --git a/XVim/XVimMotion.h b/XVim/XVimMotion.h index 55d69f65..c0f5aff2 100644 --- a/XVim/XVimMotion.h +++ b/XVim/XVimMotion.h @@ -52,6 +52,8 @@ typedef enum _MOTION{ MOTION_BOTTOM, // L jump MOTION_SEARCH_FORWARD, // / jump MOTION_SEARCH_BACKWARD, // ? jump + MOTION_SEARCH_MATCHED_FORWARD, // gn + MOTION_SEARCH_MATCHED_BACKWARD, // gN TEXTOBJECT_WORD, //TEXTOBJECT_BIGWORD, // Use motion option TEXTOBJECT_SENTENCE,