Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Perkin

macrumors newbie
Original poster
Oct 22, 2013
16
0
I'm using a NSTextview with text in, and stepping through with a regex search highlighting the match result, I then want to replace only some of the results, so I can't do a replace all.

However in the regex is a lookbehind, so the selection is then not matching again for the replace.

Any ideas on how to replace just the one match that I want?

I need to redo the search matching the regex, but with a replace on only the required one.

the search regex contains:
Code:
(?<=([^p]\.) $
which matches a space before eol char

The replace is with nothing - so it's removing the space

Say some sample text (the first three text lines all have a space char at end) is:
Code:
p. 

=(small)#. 

p. And Here's an end space. 

that last end space is the only one I want to have replaced.

The search will only match the 2nd and 3rd text lines.

The search function is as follows
Code:
- (void)searchText:(NSString *)searchString inTextView:(NSTextView *)textView options:(NSRegularExpressionOptions)options
{
    NSString *allText = textView.string;

    NSError *error;
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:searchString options:options error:&error];

    NSRange curRange = [[[textView selectedRanges] objectAtIndex:0] rangeValue];
    NSInteger insertion = curRange.location + curRange.length;
    NSRange cursorRange = NSMakeRange(insertion, allText.length - insertion);
    NSRange newSelection = [regex rangeOfFirstMatchInString:allText options:0 range:cursorRange];

    if (newSelection.location == NSNotFound) {
        NSLog(@"Not Found!");
        NSBeep();
    } else {
        [textView setSelectedRange:newSelection];
        [textView scrollRangeToVisible:newSelection];
    }
}

Which is called from
Code:
- (IBAction)clickedSearch:(id)sender {
    NSString *searchString = [findSearchField stringValue];

    NSInteger searchStringLength = [searchString length];
    if (!searchStringLength > 0) {
        NSBeep();
        return;
    }
    
    [self searchText:searchString inTextView:_textview options:NSRegularExpressionAnchorsMatchLines];

}

and the Replace function is as follows - Which I need to fix - getting more text than just selected
Code:
- (IBAction)clickedReplace:(id)sender {
    NSString *searchString = [findSearchField stringValue];
    NSString *replaceString = [findReplaceField stringValue];
    
    NSError *error;
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:searchString options:NSRegularExpressionAnchorsMatchLines error:&error];
    
    NSString *textString = [[_textview string] substringWithRange:[_textview selectedRange]];
    NSString *modifiedString = [regex stringByReplacingMatchesInString:textString options:0 range:NSMakeRange(0, [textString length]) withTemplate:replaceString];

    [_textview insertText:modifiedString];
}
 

Perkin

macrumors newbie
Original poster
Oct 22, 2013
16
0
Came up with the following solution

Code:
- (IBAction)clickedReplace:(id)sender {
    NSString *searchString = [findSearchField stringValue];
    NSString *replaceString = [findReplaceField stringValue];
    
    NSError *error;
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:searchString options:(NSRegularExpressionAnchorsMatchLines & NSRegularExpressionDotMatchesLineSeparators) error:&error];
    
    NSString *allText = [_textview string];
    NSRange selectedRange = [_textview selectedRange];
    
    NSString *modifiedText = [regex stringByReplacingMatchesInString:allText options:NSMatchingWithTransparentBounds range:selectedRange withTemplate: replaceString];
    
    NSRange alteredRange = NSMakeRange(selectedRange.location, selectedRange.length + (modifiedText.length - allText.length));
    NSString *alteredText = [modifiedText substringWithRange:alteredRange];
    
    [_textview insertText:alteredText];
}

I also handle the escape chars in the replaceString by using the function I use in this post
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.