Question

So i'm trying to get my NSTextView to syntax highlight some markdown. Here's what it looks like:

enter image description here

but when I press the delete key, this happens:

enter image description here

Does anyone know what's going on?

In my - (void)textStorageDidProcessEditing:(NSNotification *)notification delegate, I'm performing a full parse of the text, and I have a dictionary containing the entries like the following:

@"paragraph": @{NSFontAttributeName: bodyFont,
                NSUnderlineStyleAttributeName: @(NSUnderlineStyleNone),
                NSForegroundColorAttributeName: paragraphColor}

the way I apply the formatting is:

- (void) applyThemeIfRequired:(NSDictionary*)token {
  NSRange tokenRange = (NSRange)[token[@"range"] rangeValue];
  NSRange effectiveRange;
  NSTextStorage* storage = _textView.textStorage;

  NSDictionary* themeForToken = _theme[token[@"type"]];

  if (themeForToken) {
      [themeForToken enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
          id prop = [storage attribute:key atIndex:tokenRange.location effectiveRange:(NSRangePointer)&effectiveRange];
          if (![prop isEqualTo: obj] || ([prop isEqualTo:obj] && NSMaxRange(effectiveRange) < NSMaxRange(tokenRange))) {
              [storage addAttribute:key value:obj range:tokenRange];
              [storage fixAttributesInRange:tokenRange];
          }
      }];
   }
}

I've found that if I start adding attributes to the entire string, it causes this bug, and while the above code handles the block level elements (i.e. when styles are applied to the entire line) well, it restarts having this issue if the attributes are within lines.

A few more interesting details:

  • The caret doesn't have any problems while inserting text

  • If you delete the first (and only) character on the line, making it an empty line, the insertion point takes its correct place

  • The column (X-axis) location of the caret is always correct, its only the Y-Axis value that messes up.

  • for the most part, if you're editing within the document before the location where the last style was applied, this problem doesn't show up, an example of this is below. Here i've just deleted the 'g' but the caret is fine. So, the only problem is while editing within or after the last stlyed text. enter image description here

Sorry about this question being a bit long, but do ask if I've left anything out. Thanks for helping!

Was it helpful?

Solution

Ok so I've figured out the solution:

I was calling my parse method from -textStorageWillProcessEditing: method and for some reason NSAttributedString doesn't like its attributes being modified live. So, using -performSelector:withObject:afterDelay to call the parse selector with a delay of 0.0 solves the problem.

However, editing the attributes of NSTextStorage within the delayed selector causes the -textStorageWillProcessEditing: selector to be called again and again. So you have to check that with an algorithm that doesn't perform a parse when the content is already fully parsed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top