Permalink
Browse files

Add highlight action to triggers.

  • Loading branch information...
1 parent 5a9cb8f commit ef59e5745ae1ecf91e2d665d16d47fd43189299f @gnachman gnachman committed Nov 17, 2011
Showing with 390 additions and 23 deletions.
  1. +5 −1 Headers/iTerm/VT100Screen.h
  2. +18 −0 HighlightTrigger.h
  3. +151 −0 HighlightTrigger.m
  4. +1 −1 ScreenChar.h
  5. +12 −0 Trigger.h
  6. +26 −1 Trigger.m
  7. +56 −16 TriggerController.m
  8. +113 −4 VT100Screen.m
  9. +8 −0 iTerm.xcodeproj/project.pbxproj
@@ -304,7 +304,11 @@ void StringToScreenChars(NSString *s,
inContext:(FindContext*)context;
- (void)cancelFindInContext:(FindContext*)context;
-- (void) dumpDebugLog;
+- (void)dumpDebugLog;
+
+// Set the colors in the prototype char to all text on screen that matches the regex.
+- (void)highlightTextMatchingRegex:(NSString *)regex
+ prototypeChar:(screen_char_t)prototypechar;
// Return a human-readable dump of the screen contents.
- (NSString*)debugString;
View
@@ -0,0 +1,18 @@
+//
+// HighlightTrigger.h
+// iTerm2
+//
+// Created by George Nachman on 9/23/11.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "Trigger.h"
+
+@interface HighlightTrigger : Trigger
+
+- (NSString *)title;
+- (BOOL)takesParameter;
+- (BOOL)paramIsPopupButton;
+- (void)performActionWithValues:(NSArray *)values inSession:(PTYSession *)aSession;
+
+@end
View
@@ -0,0 +1,151 @@
+//
+// HighlightTrigger.m
+// iTerm2
+//
+// Created by George Nachman on 9/23/11.
+//
+
+#import "HighlightTrigger.h"
+#import "PTYSession.h"
+#import "PTYTab.h"
+#import "PseudoTerminal.h"
+#import "VT100Screen.h"
+
+// Preserve these values - they are the tags and are saved in preferences.
+enum {
+ kYellowOnBlackHighlight,
+ kBlackOnYellowHighlight,
+ kWhiteOnRedHighlight,
+ kRedOnWhiteHighlight,
+ kBlackOnOrangeHighlight,
+ kOrangeOnBlackHighlight,
+ kBlackOnPurpleHighlight,
+ kPurpleOnBlackHighlight,
+};
+
+@implementation HighlightTrigger
+
+- (NSString *)title
+{
+ return @"Highlight Text…";
+}
+
+- (NSString *)paramPlaceholder
+{
+ return @"";
+}
+
+- (BOOL)takesParameter
+{
+ return YES;
+}
+
+- (BOOL)paramIsPopupButton
+{
+ return YES;
+}
+
+- (NSDictionary *)menuItemsForPoupupButton
+{
+ return [NSDictionary dictionaryWithObjectsAndKeys:
+ @"Yellow on Black", [NSNumber numberWithInt:(int)kYellowOnBlackHighlight],
+ @"Black on Yellow", [NSNumber numberWithInt:(int)kBlackOnYellowHighlight],
+ @"White on Red", [NSNumber numberWithInt:(int)kWhiteOnRedHighlight],
+ @"Red on White", [NSNumber numberWithInt:(int)kRedOnWhiteHighlight],
+ @"Black on Orange", [NSNumber numberWithInt:(int)kBlackOnOrangeHighlight],
+ @"Orange on Black", [NSNumber numberWithInt:(int)kOrangeOnBlackHighlight],
+ @"Purple on Black", [NSNumber numberWithInt:(int)kPurpleOnBlackHighlight],
+ @"Black on Purple", [NSNumber numberWithInt:(int)kBlackOnPurpleHighlight],
+ nil];
+}
+
+- (NSArray *)tagsSortedByValue
+{
+ return [[self menuItemsForPoupupButton] keysSortedByValueUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
+}
+
+- (int)indexOfTag:(int)theTag
+{
+ int i = 0;
+ for (NSNumber *n in [self tagsSortedByValue]) {
+ if ([n intValue] == theTag) {
+ return i;
+ }
+ i++;
+ }
+ return -1;
+}
+
+- (int)tagAtIndex:(int)theIndex
+{
+ return [[[self tagsSortedByValue] objectAtIndex:theIndex] intValue];
+}
+
+- (int)colorCodeForColor:(NSColor *)theColor
+{
+ theColor = [theColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
+ int r = 5 * [theColor redComponent];
+ int g = 5 * [theColor greenComponent];
+ int b = 5 * [theColor blueComponent];
+ return 16 + b + g*6 + r*36;
+}
+
+- (screen_char_t)prototypeChar
+{
+ screen_char_t sct;
+ sct.alternateBackgroundSemantics = NO;
+ sct.alternateForegroundSemantics = NO;
+ sct.bold = NO;
+ sct.blink = NO;
+ sct.underline = NO;
+ switch ([self.param intValue]) {
+ case kYellowOnBlackHighlight:
+ sct.foregroundColor = [self colorCodeForColor:[NSColor yellowColor]];
+ sct.backgroundColor = [self colorCodeForColor:[NSColor blackColor]];
+ break;
+
+ case kBlackOnYellowHighlight:
+ sct.foregroundColor = [self colorCodeForColor:[NSColor blackColor]];
+ sct.backgroundColor = [self colorCodeForColor:[NSColor yellowColor]];
+ break;
+
+ case kWhiteOnRedHighlight:
+ sct.foregroundColor = [self colorCodeForColor:[NSColor whiteColor]];
+ sct.backgroundColor = [self colorCodeForColor:[NSColor redColor]];
+ break;
+
+ case kRedOnWhiteHighlight:
+ sct.foregroundColor = [self colorCodeForColor:[NSColor redColor]];
+ sct.backgroundColor = [self colorCodeForColor:[NSColor whiteColor]];
+ break;
+
+ case kBlackOnOrangeHighlight:
+ sct.foregroundColor = [self colorCodeForColor:[NSColor blackColor]];
+ sct.backgroundColor = [self colorCodeForColor:[NSColor orangeColor]];
+ break;
+
+ case kOrangeOnBlackHighlight:
+ sct.foregroundColor = [self colorCodeForColor:[NSColor orangeColor]];
+ sct.backgroundColor = [self colorCodeForColor:[NSColor blackColor]];
+ break;
+
+ case kBlackOnPurpleHighlight:
+ sct.foregroundColor = [self colorCodeForColor:[NSColor blackColor]];
+ sct.backgroundColor = [self colorCodeForColor:[NSColor purpleColor]];
+ break;
+
+ case kPurpleOnBlackHighlight:
+ sct.foregroundColor = [self colorCodeForColor:[NSColor purpleColor]];
+ sct.backgroundColor = [self colorCodeForColor:[NSColor blackColor]];
+ break;
+ }
+ return sct;
+}
+
+- (void)performActionWithValues:(NSArray *)values inSession:(PTYSession *)aSession
+{
+ [[aSession SCREEN] highlightTextMatchingRegex:self.regex
+ prototypeChar:[self prototypeChar]];
+}
+
+@end
View
@@ -101,7 +101,7 @@ typedef struct screen_char_t
// Values between 8 and 15 are bright versions of 0-7.
// Values between 16 and 255 are used for 256 color mode:
// 16-232: rgb value given by 16 + r*36 + g*6 + b, with each color in
- // the range [0,6].
+ // the range [0,5].
// 233-255: Grayscale values from dimmest gray 233 (which is not black)
// to brightest 255 (not white).
// With alternate background semantics:
View
@@ -29,6 +29,18 @@ extern NSString * const kTriggerParameterKey;
- (NSString *)title;
- (BOOL)takesParameter;
- (NSString *)paramPlaceholder;
+// Returns true if this kind of action takes a parameter.
+- (BOOL)takesParameter;
+// Returns true if the parameter this action takes is a popupbutton.
+- (BOOL)paramIsPopupButton;
+// Returns a map from NSNumber(tag) -> NSString(title)
+- (NSDictionary *)menuItemsForPoupupButton;
+// Index in tagsSortedByValue of "tag".
+- (int)indexOfTag:(int)theTag;
+// Tag at "index" in tagsSortedByValue.
+- (int)tagAtIndex:(int)index;
+// Tags in menu;ItemsForPopupButton sorted by value (however the subclass sees fit to sort)
+- (NSArray *)tagsSortedByValue;
- (NSString *)paramWithBackreferencesReplacedWithValues:(NSArray *)values;
- (void)tryString:(NSString *)s inSession:(PTYSession *)aSession;
View
@@ -49,11 +49,21 @@ - (BOOL)takesParameter
assert(false);
}
+- (BOOL)paramIsPopupButton
+{
+ return NO;
+}
+
+- (NSDictionary *)menuItemsForPoupupButton
+{
+ return nil;
+}
+
- (void)dealloc {
[regex_ release];
[action_ release];
[param_ release];
-
+
[super dealloc];
}
@@ -99,4 +109,19 @@ - (NSComparisonResult)compareTitle:(Trigger *)other
return [[self title] compare:[other title]];
}
+- (int)indexOfTag:(int)theTag
+{
+ return theTag;
+}
+
+- (int)tagAtIndex:(int)theIndex
+{
+ return 0;
+}
+
+- (NSArray *)tagsSortedByValue
+{
+ return nil;
+}
+
@end
View
@@ -13,18 +13,11 @@
#import "BellTrigger.h"
#import "ScriptTrigger.h"
#import "AlertTrigger.h"
+#import "HighlightTrigger.h"
#import "Trigger.h"
#import "CoprocessTrigger.h"
#import "SendTextTrigger.h"
-enum {
- kGrowlAction,
- kBounceAction,
- kBellAction,
- kScriptAction,
- kAlertAction
-};
-
static NSMutableArray *gTriggerClasses;
@implementation TriggerController
@@ -43,6 +36,8 @@ + (void)initialize
[gTriggerClasses addObject:[[SendTextTrigger alloc] init]];
[gTriggerClasses addObject:[[ScriptTrigger alloc] init]];
[gTriggerClasses addObject:[[CoprocessTrigger alloc] init]];
+ [gTriggerClasses addObject:[[HighlightTrigger alloc] init]];
+
[gTriggerClasses sortUsingSelector:@selector(compareTitle:)];
}
@@ -69,6 +64,17 @@ + (int)indexOfAction:(NSString *)action
return -1;
}
+// Index in gTriggerClasses of an object of class "c"
++ (NSInteger)indexOfTriggerClass:(Class)c
+{
+ for (int i = 0; i < gTriggerClasses.count; i++) {
+ if ([[gTriggerClasses objectAtIndex:i] isKindOfClass:c]) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+ (Trigger *)triggerAtIndex:(int)i
{
return [gTriggerClasses objectAtIndex:i];
@@ -140,7 +146,7 @@ - (NSDictionary *)defaultTrigger
{
return [NSDictionary dictionaryWithObjectsAndKeys:
@"", kTriggerRegexKey,
- [[TriggerController triggerAtIndex:kBounceAction] action], kTriggerActionKey,
+ [[TriggerController triggerAtIndex:[TriggerController indexOfTriggerClass:[BounceTrigger class]]] action], kTriggerActionKey,
nil];
}
@@ -182,8 +188,19 @@ - (id)tableView:(NSTableView *)aTableView
return [trigger objectForKey:kTriggerRegexKey];
} else if (aTableColumn == parametersColumn_) {
NSString *action = [trigger objectForKey:kTriggerActionKey];
- if ([[TriggerController triggerWithAction:action] takesParameter]) {
- return [trigger objectForKey:kTriggerParameterKey];
+ Trigger *triggerObj = [TriggerController triggerWithAction:action];
+ if ([triggerObj takesParameter]) {
+ id param = [trigger objectForKey:kTriggerParameterKey];
+ if ([triggerObj paramIsPopupButton]) {
+ if (!param) {
+ // Force popup buttons to have the first item selected by default
+ return [NSNumber numberWithInt:0];
+ } else {
+ return [NSNumber numberWithInt:[triggerObj indexOfTag:[param intValue]]];
+ }
+ } else {
+ return param;
+ }
} else {
return @"";
}
@@ -200,10 +217,18 @@ - (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject forTable
if (aTableColumn == regexColumn_) {
[trigger setObject:anObject forKey:kTriggerRegexKey];
} else if (aTableColumn == parametersColumn_) {
- [trigger setObject:anObject forKey:kTriggerParameterKey];
+ Trigger *triggerObj = [TriggerController triggerWithAction:[trigger objectForKey:kTriggerActionKey]];
+ if ([triggerObj paramIsPopupButton]) {
+ int theTag = [triggerObj tagAtIndex:[anObject intValue]];
+ [trigger setObject:[NSNumber numberWithInt:theTag] forKey:kTriggerParameterKey];
+ } else {
+ [trigger setObject:anObject forKey:kTriggerParameterKey];
+ }
} else {
+ // Action column
[trigger setObject:[[TriggerController triggerAtIndex:[anObject intValue]] action]
forKey:kTriggerActionKey];
+ [trigger removeObjectForKey:kTriggerParameterKey];
}
[self setTrigger:trigger forRow:rowIndex];
}
@@ -243,10 +268,25 @@ - (NSCell *)tableView:(NSTableView *)tableView
} else if (tableColumn == parametersColumn_) {
Trigger *trigger = [TriggerController triggerWithAction:[[[self triggers] objectAtIndex:row] objectForKey:kTriggerActionKey]];
if ([trigger takesParameter]) {
- NSTextFieldCell *cell = [[[NSTextFieldCell alloc] initTextCell:@""] autorelease];
- [cell setPlaceholderString:[trigger paramPlaceholder]];
- [cell setEditable:YES];
- return cell;
+ if ([trigger paramIsPopupButton]) {
+ NSPopUpButtonCell *cell = [[[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO] autorelease];
+ NSMenu *theMenu = [cell menu];
+ NSDictionary *items = [trigger menuItemsForPoupupButton];
+ for (NSNumber *n in [trigger tagsSortedByValue]) {
+ NSString *theTitle = [items objectForKey:n];
+ NSMenuItem *anItem = [[[NSMenuItem alloc] initWithTitle:theTitle action:nil keyEquivalent:@""] autorelease];
+ [anItem setTag:[n intValue]];
+ [theMenu addItem:anItem];
+ }
+ [cell setBordered:NO];
+ return cell;
+ } else {
+ // If not a popup button, then text by default.
+ NSTextFieldCell *cell = [[[NSTextFieldCell alloc] initTextCell:@""] autorelease];
+ [cell setPlaceholderString:[trigger paramPlaceholder]];
+ [cell setEditable:YES];
+ return cell;
+ }
} else {
NSTextFieldCell *cell = [[[NSTextFieldCell alloc] initTextCell:@""] autorelease];
[cell setPlaceholderString:@""];
Oops, something went wrong.

0 comments on commit ef59e57

Please sign in to comment.