Re: NSTextView and Syntax Highlighting
Re: NSTextView and Syntax Highlighting
- Subject: Re: NSTextView and Syntax Highlighting
- From: Charles Jenkins <email@hidden>
- Date: Sat, 20 Dec 2014 08:33:11 -0500
Martin, Ecir, and Quincey:
Thank you all! All three answers turned out to be helpful. (Quincey, you led me to learn about how to get attributed substrings, should I ever need to do it.)
Martin, your chief difference from my code seems be calling the layout manager’s ensureGlyphsForCharacterRange: in order to synch up the layout manager with the current content of text storage. I took that and ran with it. Here is the resulting code that works for me, which I donate to the public domain in case anyone else finds it useful.
The methods below are found in a subclass of NSTextView:
/// Set temporary foreground color for special characters in the given range
-(void)setTemporaryForegroundColor:(NSColor*)color
forSpecialCharacters:(NSCharacterSet*)characterSet
inRange:(NSRange)range
{
HighlightInfo* hi = [[HighlightInfo alloc] initWithColor:color
characterSet:characterSet
range:range];
// If we don't delay for a half-second, Apple's Smart Quotes stop working.
// I think this is a bug: why should altering temporary attributes lock out substitution?
static double smartQuoteDelay = 0.5;
[self performSelector:@selector(setTemporaryForegroundColor:)
withObject:hi
afterDelay:smartQuoteDelay];
}
/// Set temporary foreground color according to information passed in HighlightInfo
/// @attention Keep this private and always call via performSelector:withObject:afterDelay:
-(void)setTemporaryForegroundColor:(HighlightInfo*)hi
{
NSLayoutManager* lm = self.layoutManager;
NSTextStorage* ts = self.textStorage;
NSRange searchRange = hi.range;
NSUInteger beyondIx = searchRange.location + searchRange.length;
// Synchronize layoutManager with textStorage: otherwise temp attribute ranges don't agree
[lm ensureGlyphsForCharacterRange:searchRange];
[lm removeTemporaryAttribute:NSForegroundColorAttributeName
forCharacterRange:searchRange];
// Repeatedly search and apply temporary attributes to special characters in search range
NSString* str = ts.string;
//NSLog( @"Searching for special chars in: %@", [str substringWithRange:searchRange]);
NSCharacterSet* set = hi.characterSet;
NSDictionary* tempAttrs = @{ NSForegroundColorAttributeName : hi.color };
while ( true ) {
NSRange foundRange = [str rangeOfCharacterFromSet:set
options:0
range:searchRange];
if ( foundRange.location == NSNotFound ) {
break;
}
[lm setTemporaryAttributes:tempAttrs forCharacterRange:foundRange];
NSUInteger startIx = foundRange.location + foundRange.length;
if ( startIx >= beyondIx ) {
break;
}
searchRange = NSMakeRange( startIx, beyondIx - startIx );
}
}
The definition of HighlightInfo should be obvious, but here it is anyway:
@interface HighlightInfo : NSObject
@property (nonatomic) NSColor* color;
@property (nonatomic) NSCharacterSet* characterSet;
@property (nonatomic) NSRange range;
-(instancetype)initWithColor:(NSColor*)color
characterSet:(NSCharacterSet*)characterSet
range:(NSRange)range;
@end
Cheers and happy holidays to all!
—
Charles Jenkins
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden