From 6669fdc5934609e188b5d23e7d8db25baac88a30 Mon Sep 17 00:00:00 2001 From: David Quon Date: Fri, 11 Oct 2013 14:54:35 -0700 Subject: [PATCH 1/4] Fix == functionality to match VIM --- XVim/NSTextView+VimOperation.m | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/XVim/NSTextView+VimOperation.m b/XVim/NSTextView+VimOperation.m index 8e112d7d..60e3f87d 100644 --- a/XVim/NSTextView+VimOperation.m +++ b/XVim/NSTextView+VimOperation.m @@ -789,8 +789,8 @@ - (void)xvim_filter:(XVimMotion*)motion{ if( self.insertionPoint == 0 && [[self xvim_string] length] == 0 ){ return ; } - - NSUInteger insertionAfterFilter = self.insertionPoint; + + NSUInteger insertionAfterFilter; NSRange filterRange; if( self.selectionMode == XVIM_VISUAL_NONE ){ XVimRange to = [self xvim_getMotionRange:self.insertionPoint Motion:motion]; @@ -799,19 +799,22 @@ - (void)xvim_filter:(XVimMotion*)motion{ } filterRange = [self xvim_getOperationRangeFrom:to.begin To:to.end Type:LINEWISE]; }else{ - insertionAfterFilter = [[[self xvim_selectedRanges] lastObject] rangeValue].location; NSUInteger start = [[[self xvim_selectedRanges] objectAtIndex:0] rangeValue].location; NSRange lastSelection = [[[self xvim_selectedRanges] lastObject] rangeValue]; NSUInteger end = lastSelection.location + lastSelection.length - 1; filterRange = NSMakeRange(start, end-start+1); } - + + NSString *lineString = [[self xvim_string] substringWithRange:filterRange]; + NSRange whiteSpaceRange = [lineString rangeOfString:@"^\\s*" options:NSRegularExpressionSearch]; + lineString = [lineString stringByReplacingCharactersInRange:whiteSpaceRange withString:@""]; + [self xvim_indentCharacterRange: filterRange]; + insertionAfterFilter = [self.textStorage firstNonblankInLine:self.insertionPoint]; [self xvim_moveCursor:insertionAfterFilter preserveColumn:NO]; [self xvim_changeSelectionMode:XVIM_VISUAL_NONE]; } - - (void)xvim_shiftRight:(XVimMotion*)motion{ [self xvim_shfit:motion right:YES]; } From 986fae76584cbbcb80c0dccd04751efd19ab4b38 Mon Sep 17 00:00:00 2001 From: David Quon Date: Mon, 14 Oct 2013 12:59:56 -0700 Subject: [PATCH 2/4] Add = and == (filter) tests and documentation --- Documents/Users/FeatureList.md | 6 ++++++ XVim/Test/XVimTester+Operator.m | 27 +++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/Documents/Users/FeatureList.md b/Documents/Users/FeatureList.md index 7ece9f6f..ad1c1ba8 100644 --- a/Documents/Users/FeatureList.md +++ b/Documents/Users/FeatureList.md @@ -53,6 +53,12 @@ J Normal mode: >, >>, <, << +## Filter + +Normal mode: == + +Visual mode: = + ## Case change operations Normal mode: ~, gu, gU, g~ diff --git a/XVim/Test/XVimTester+Operator.m b/XVim/Test/XVimTester+Operator.m index 6af6298b..162f2a12 100644 --- a/XVim/Test/XVimTester+Operator.m +++ b/XVim/Test/XVimTester+Operator.m @@ -55,7 +55,16 @@ - (NSArray*)operator_testcases{ @"ddd\n" // 52 @"eee\n" // 56 @"fff\n"; // 60 - + + static NSString* text7 = @"aaa\n" // 0 (index of each WORD) + @"{\n" // 4 + @" bbb\n" // 6 + @"}\n"; // 18 + + static NSString* text8 = @" \n"; // 0 (index of each WORD) + + static NSString* text9 = @"\t\t\n"; // 0 (index of each WORD) + static NSString* a_result = @"aAa bbXXXb ccc\n"; static NSString* a_result2 = @"aAa bbXXXXXXXXXb ccc\n"; static NSString* a_result3 = @"aXXXaa\n" @@ -304,7 +313,14 @@ - (NSArray*)operator_testcases{ @" ddd\n" // 28 @" eee\n" // 38 @" fff"; // 46 - + + static NSString* filter_result0 = @"aaa\n" // 0 (index of each WORD) + @"{\n" // 4 + @" bbb\n" // 6 + @"}\n"; // 14 + + static NSString* filter_result1 = @"\n"; // 0 (index of each WORD) + return [NSArray arrayWithObjects: // All changes/insertions must be repeated by dot(.) // All insertions must set hat(^) mark @@ -485,9 +501,12 @@ - (NSArray*)operator_testcases{ XVimMakeTestCase(text5, 1, 0, @"2< Date: Fri, 18 Oct 2013 13:13:33 -0700 Subject: [PATCH 3/4] Fix filter operation when all whitespace --- XVim/NSTextView+VimOperation.m | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/XVim/NSTextView+VimOperation.m b/XVim/NSTextView+VimOperation.m index 21d37e63..affe3fdc 100644 --- a/XVim/NSTextView+VimOperation.m +++ b/XVim/NSTextView+VimOperation.m @@ -807,9 +807,18 @@ - (void)xvim_filter:(XVimMotion*)motion{ NSString *lineString = [[self xvim_string] substringWithRange:filterRange]; NSRange whiteSpaceRange = [lineString rangeOfString:@"^\\s*" options:NSRegularExpressionSearch]; - lineString = [lineString stringByReplacingCharactersInRange:whiteSpaceRange withString:@""]; + if (whiteSpaceRange.length == filterRange.length) { + whiteSpaceRange.length = whiteSpaceRange.length - 1; + lineString = [lineString stringByReplacingCharactersInRange:whiteSpaceRange withString:@""]; + whiteSpaceRange.location = filterRange.location + whiteSpaceRange.location; + [self insertText:lineString replacementRange:filterRange]; + filterRange.length = filterRange.length - whiteSpaceRange.length; + self.insertionPoint = filterRange.location; + } + else { + [self xvim_indentCharacterRange: filterRange]; + } - [self xvim_indentCharacterRange: filterRange]; insertionAfterFilter = [self.textStorage firstNonblankInLine:self.insertionPoint]; [self xvim_moveCursor:insertionAfterFilter preserveColumn:NO]; [self xvim_changeSelectionMode:XVIM_VISUAL_NONE]; From 8912cab9624b01068c542e00fe36e7ed20b69968 Mon Sep 17 00:00:00 2001 From: David Quon Date: Mon, 28 Oct 2013 18:11:27 -0700 Subject: [PATCH 4/4] WIP: Close but no cigar --- XVim/NSTextView+VimOperation.m | 70 +++++++++++++++------------------- 1 file changed, 31 insertions(+), 39 deletions(-) diff --git a/XVim/NSTextView+VimOperation.m b/XVim/NSTextView+VimOperation.m index affe3fdc..c2a41ec7 100644 --- a/XVim/NSTextView+VimOperation.m +++ b/XVim/NSTextView+VimOperation.m @@ -790,36 +790,26 @@ - (void)xvim_filter:(XVimMotion*)motion{ return ; } - NSUInteger insertionAfterFilter; - NSRange filterRange; - if( self.selectionMode == XVIM_VISUAL_NONE ){ - XVimRange to = [self xvim_getMotionRange:self.insertionPoint Motion:motion]; - if( to.end == NSNotFound ){ - return; + NSArray* ranges = [self xvim_selectedRanges]; + self.insertionPoint = [[ranges objectAtIndex:0] rangeValue].location; + NSUInteger insertionAfterFilter = [self.textStorage firstNonblankInLine:self.insertionPoint]; + + for( NSValue* val in ranges){ + NSRange filterRange = val.rangeValue; + NSString *lineString = [[self xvim_string] substringWithRange:filterRange]; + NSRange whiteSpaceRange = [lineString rangeOfString:@"^\\s*" options:NSRegularExpressionSearch]; + if (whiteSpaceRange.length == filterRange.length) { + whiteSpaceRange.length = whiteSpaceRange.length - 1; + lineString = [lineString stringByReplacingCharactersInRange:whiteSpaceRange withString:@""]; + whiteSpaceRange.location = filterRange.location + whiteSpaceRange.location; + [self insertText:lineString replacementRange:filterRange]; + filterRange.length = filterRange.length - whiteSpaceRange.length; + } + else { + [self xvim_indentCharacterRange: filterRange]; } - filterRange = [self xvim_getOperationRangeFrom:to.begin To:to.end Type:LINEWISE]; - }else{ - NSUInteger start = [[[self xvim_selectedRanges] objectAtIndex:0] rangeValue].location; - NSRange lastSelection = [[[self xvim_selectedRanges] lastObject] rangeValue]; - NSUInteger end = lastSelection.location + lastSelection.length - 1; - filterRange = NSMakeRange(start, end-start+1); - } - - NSString *lineString = [[self xvim_string] substringWithRange:filterRange]; - NSRange whiteSpaceRange = [lineString rangeOfString:@"^\\s*" options:NSRegularExpressionSearch]; - if (whiteSpaceRange.length == filterRange.length) { - whiteSpaceRange.length = whiteSpaceRange.length - 1; - lineString = [lineString stringByReplacingCharactersInRange:whiteSpaceRange withString:@""]; - whiteSpaceRange.location = filterRange.location + whiteSpaceRange.location; - [self insertText:lineString replacementRange:filterRange]; - filterRange.length = filterRange.length - whiteSpaceRange.length; - self.insertionPoint = filterRange.location; - } - else { - [self xvim_indentCharacterRange: filterRange]; } - insertionAfterFilter = [self.textStorage firstNonblankInLine:self.insertionPoint]; [self xvim_moveCursor:insertionAfterFilter preserveColumn:NO]; [self xvim_changeSelectionMode:XVIM_VISUAL_NONE]; } @@ -1568,18 +1558,20 @@ - (NSArray*)xvim_selectedRanges{ [rangeArray addObject:[NSValue valueWithRange:NSMakeRange(selectionStart,selectionEnd-selectionStart+1)]]; } }else if(self.selectionMode == XVIM_VISUAL_LINE ){ - NSUInteger min = MIN(self.insertionPoint,self.selectionBegin); - NSUInteger max = MAX(self.insertionPoint,self.selectionBegin); - selectionStart = [self.textStorage beginningOfLine:min]; - selectionEnd = [self.textStorage endOfLine:max]; - if( [self.textStorage isEOF:selectionStart] ){ - // EOF can not be selected - [rangeArray addObject:[NSValue valueWithRange:NSMakeRange(selectionStart,0)]]; - }else if( [self.textStorage isEOF:selectionEnd] ){ - selectionEnd--; - [rangeArray addObject:[NSValue valueWithRange:NSMakeRange(selectionStart,selectionEnd-selectionStart+1)]]; - }else{ - [rangeArray addObject:[NSValue valueWithRange:NSMakeRange(selectionStart,selectionEnd-selectionStart+1)]]; + NSUInteger top = MIN( [self.textStorage lineNumber:self.insertionPoint], [self.textStorage lineNumber:self.selectionBegin] ); + NSUInteger bottom = MAX( [self.textStorage lineNumber:self.insertionPoint], [self.textStorage lineNumber:self.selectionBegin] ); + for( NSUInteger i = 0; i < bottom-top+1 ; i++ ){ + selectionStart = [self.textStorage positionAtLineNumber:top+i column:0]; + selectionEnd = [self.textStorage positionAtLineNumber:top+i column:[self.textStorage numberOfLines]]; + if( [self.textStorage isEOF:selectionStart] || [self.textStorage isEOL:selectionStart]){ + // EOF or EOL can not be selected + [rangeArray addObject:[NSValue valueWithRange:NSMakeRange(selectionStart,0)]]; // 0 means No selection. This information is important and used in operators like 'delete' + }else if( [self.textStorage isEOF:selectionEnd] || [self.textStorage isEOL:selectionEnd]){ + selectionEnd--; + [rangeArray addObject:[NSValue valueWithRange:NSMakeRange(selectionStart,selectionEnd-selectionStart+1)]]; + }else{ + [rangeArray addObject:[NSValue valueWithRange:NSMakeRange(selectionStart,selectionEnd-selectionStart+1)]]; + } } }else if( self.selectionMode == XVIM_VISUAL_BLOCK){ // Define the block as a rect by line and column number