Reputation: 6918
In Xcode, if you type <# Hello, Word #>
into the text editor, it automatically gets converted to a pale-blue pill-shaped placeholder, but on disk, the text remains exactly as it was typed. Does anyone know if the same effect is achievable using NSTextView
? I've got some very ugly filepaths that must remain exactly as they are so sphinx
can put together my docs, but I want to present the user with something a little more attractive when they view the file in my custom text editor.
// This on disk (and in any other text editor)
.. image:: images/ssafs/sdfd-sdfsdg-ewfsdf.png
// This shown to the user in my custom text editor
Image of a golden eagle
Upvotes: 5
Views: 1900
Reputation: 13429
As much as possible tried to write explanations as a comment in code. What I have done here.
.. image:: images/ssafs/sdfd-sdfsdg-ewfsdf1.png
with Regex and add them into an array... image:: images/ssafs/sdfd-sdfsdg-ewfsdf1.png
with [Image] stringIt does what you are asking and it does on the fly, your source in the database/file does not change at all.
.h
#import <Cocoa/Cocoa.h>
@interface AppDelegate : NSObject <NSApplicationDelegate, NSTextViewDelegate>
@property (unsafe_unretained) IBOutlet NSTextView *aTextView;
.m
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
//Your NSTextView
[aTextView setDelegate:(id)self];
// The Context
NSString *string = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec convallis .. image:: images/ssafs/sdfd-sdfsdg-ewfsdf1.png lacinia diam, in mattis quam egestas in. Nam gravida dolor adipiscing velit faucibus, vulputate facilisis diam facilisis. Duis id magna nibh. Proin sed turpis aliquet .. image:: images/ssafs/sdfd-sdfsdg-ewfsdf2.png, posuere purus eget, condimentum nulla. Aenean erat odio, suscipit eu aliquet eget, porta in justo. Quisque sed sem dignissim, luctus .. image:: images/ssafs/sdfd-sdfsdg-ewfsdf3.png libero ut, congue libero. Curabitur tristique fermentum risus in fermentum.";
//Regex to find your links .. image:: images/ssafs/sdfd-sdfsdg-ewfsdf2.png
//You can / should improve Reges patter.
NSRegularExpression *regexPatternForFullLinks = [NSRegularExpression regularExpressionWithPattern:@"(\\.\\.\\s(.*?\\.png))"
options:NSRegularExpressionCaseInsensitive error:nil];
//Here find all image links and add them into an Array
NSArray *arrayOfAllMatches = [regexPatternForFullLinks matchesInString:string options:0 range:NSMakeRange(0, string.length)];
NSMutableArray *links = [[NSMutableArray alloc] init];
for (NSTextCheckingResult *match in arrayOfAllMatches) {
[links addObject:[[string substringWithRange:match.range] stringByReplacingOccurrencesOfString:@".. image:: " withString:@"/"]];
}
//Replacing All your links with string: [Image]
NSString *modifiedString = [regexPatternForFullLinks stringByReplacingMatchesInString:string
options:0
range:NSMakeRange(0, [string length])
withTemplate:@"[Image]"];
NSRegularExpression *regexPatternReplaceLinksWithIMAGEStr = [NSRegularExpression regularExpressionWithPattern:@"\\[image\\]"
options:NSRegularExpressionCaseInsensitive error:nil];
NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] initWithString:modifiedString];
//Here,looking for all [Image] strings and add them Link Attribute
NSArray *arrayOfAllMatchesImageText = [regexPatternReplaceLinksWithIMAGEStr matchesInString:modifiedString
options:0
range:NSMakeRange(0, modifiedString.length)];
for (int i = 0; i < arrayOfAllMatchesImageText.count; i++) {
NSTextCheckingResult *checkingResult = [arrayOfAllMatchesImageText objectAtIndex:i];
[attrString beginEditing];
[attrString addAttribute:NSLinkAttributeName value:[links objectAtIndex:i] range:checkingResult.range];
[attrString addAttribute:NSForegroundColorAttributeName value:[NSColor greenColor] range:checkingResult.range];
[attrString addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInt:0] range:checkingResult.range];
[attrString endEditing];
}
//Set NSTextView Storage text...
[aTextView.textStorage setAttributedString:attrString];
}
NSTextViewDelegate: clickedOnLink to handle link clicks.
//Open Given Links with Preview App - NSTextViewDelegate
- (BOOL)textView:(NSTextView *)aTextView clickedOnLink:(id)link atIndex:(NSUInteger)charIndex {
[[NSWorkspace sharedWorkspace] openFile:link withApplication:@"Preview"];
NSLog(@"%@", link);
return YES;
}
You can see final result on the image. If you want you can give background color to links as well.
NSTextView settings are important as well.
Just figure out this can be done more elegantly and it is efficient (faster).
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
//Your NSTextView
[aTextView setDelegate:(id)self];
// The Context
NSString *string = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec convallis .. image:: images/ssafs/sdfd-sdfsdg-ewfsdf1.png lacinia diam, in mattis quam egestas in. Nam gravida dolor adipiscing velit faucibus, vulputate facilisis diam facilisis. Duis id magna nibh. Proin sed turpis aliquet .. image:: images/ssafs/sdfd-sdfsdg-ewfsdf2.png, posuere purus eget, condimentum nulla. Aenean erat odio, suscipit eu aliquet eget, porta in justo. Quisque sed sem dignissim, luctus .. image:: images/ssafs/sdfd-sdfsdg-ewfsdf3.png libero ut, congue libero. Curabitur tristique fermentum risus in fermentum.";
//Regex to find your links .. image:: images/ssafs/sdfd-sdfsdg-ewfsdf2.png
//You can / should improve Reges patter.
NSRegularExpression *regexPatternForFullLinks = [NSRegularExpression regularExpressionWithPattern:@"(\\.\\.\\s(.*?\\.png))"
options:NSRegularExpressionCaseInsensitive error:nil];
//Here find all image links and add them into an Array
NSArray *arrayOfAllMatches = [regexPatternForFullLinks matchesInString:string options:0 range:NSMakeRange(0, string.length)];
__block NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] initWithString:string];
[arrayOfAllMatches enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSTextCheckingResult *match = [arrayOfAllMatches objectAtIndex:idx];
NSString *linkValue = [[string substringWithRange:match.range] stringByReplacingOccurrencesOfString:@".. image:: " withString:@"/"];
NSDictionary *linkAttributes = @{NSForegroundColorAttributeName: [NSColor greenColor],
NSUnderlineStyleAttributeName: [NSNumber numberWithInt:0],
NSLinkAttributeName:linkValue};
NSMutableAttributedString *tempAttrString = [[NSMutableAttributedString alloc] initWithString:@"[Image]" attributes:linkAttributes];
[attrString beginEditing];
[attrString replaceCharactersInRange:match.range withAttributedString:tempAttrString];
[attrString endEditing];
}];
[aTextView.textStorage setAttributedString:attrString];
}
Upvotes: 5
Reputation: 7534
I think you can do this sort of thing with NSTextAttachment
and a custom subclass of NSTextAttachmentCell
.
Basically create an NSAttributedString
with your and NSTextAtachment
that is using your custom NSTextAttachmentCell
Source code examples:
from the BGHUDAppKit framework
and an extension of that class for colorization from e.printstacktrace()
Edit: it looks like the NSTokenAttachmentCell
from BGHUD is actually a private apple class. so you could just use that directly if you dont need to be AppStore compliant.
Upvotes: 0