-
Notifications
You must be signed in to change notification settings - Fork 1
/
NSTextView+IATitlecase.m
56 lines (51 loc) · 2.21 KB
/
NSTextView+IATitlecase.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
//
// NSTextView+IATitlecase.m
// Titlecase
//
// Copyright © 2016 Information Architects Inc. All rights reserved.
//
#import "NSTextView+IATitlecase.h"
#import "NSString+IATitlecase.h"
#import "Aspects.h"
@implementation NSTextView (IATitlecase)
+ (void)load {
// Implemented using aspects because we want every text entry to have “Make Title Case”. NSTextField uses NSTextView under the hood, so it gets the menus too.
NSError *error;
[self aspect_hookSelector:@selector(menuForEvent:) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo) {
// __unsafe_unretained prevents ARC from overreleasing menu at the end.
__unsafe_unretained NSMenu *menu;
[[aspectInfo originalInvocation] getReturnValue:&menu];
for (NSMenuItem *menuItem in menu.itemArray.reverseObjectEnumerator) {
if (menuItem.hasSubmenu == NO) {
continue;
}
NSInteger capitalizeIndex = [menuItem.submenu indexOfItemWithTarget:nil andAction:@selector(capitalizeWord:)];
if (capitalizeIndex != -1) {
NSMenuItem *capitalizeAsTitleItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Make Title Case", @"Title case transform title.") action:@selector(titlecaseWord:) keyEquivalent:@""];
[menuItem.submenu addItem:capitalizeAsTitleItem];
break;
}
}
} error:&error];
}
- (void)titlecaseWord:(id)sender {
if (self.isEditable == NO) {
return;
}
[self selectWord:self];
NSArray<NSValue *> *ranges = self.selectedRanges.copy;
NSMutableArray<NSString *> *strings = [[NSMutableArray alloc] init];
for (NSValue *rangeValue in ranges) {
NSString *text = [self.string substringWithRange:rangeValue.rangeValue];
NSString *titlecaseText = text.titlecaseString;
[strings addObject:titlecaseText];
}
if ([self shouldChangeTextInRanges:ranges replacementStrings:strings] == NO) {
return;
}
for (NSInteger rangeIndex = 0; rangeIndex < ranges.count; rangeIndex++) {
[self replaceCharactersInRange:ranges[rangeIndex].rangeValue withString:strings[rangeIndex]];
}
[self setSelectedRanges:ranges];
}
@end