Add search modes for git pickaxe

Add two new search modes to search the commits for strings that were added or removed in a commit.
    - match by string or an extended POSIX regex (see man git-log -S<string> and --pickaxe-regex)
    - include the modes in the search menu
    - store the current mode in user defaults
    - show progress indicator when search takes time
This commit is contained in:
Nathan Kinsinger
2010-09-06 15:22:51 -06:00
parent 62aa99b761
commit 71cdb0dbe0
5 changed files with 266 additions and 10 deletions
+2
View File
@@ -34,5 +34,7 @@
+ (void) removePreviousDocumentPaths;
+ (NSInteger) branchFilter;
+ (void) setBranchFilter:(NSInteger)state;
+ (NSInteger)historySearchMode;
+ (void)setHistorySearchMode:(NSInteger)mode;
@end
+15
View File
@@ -7,6 +7,7 @@
//
#import "PBGitDefaults.h"
#import "PBHistorySearchController.h"
#define kDefaultVerticalLineLength 50
#define kCommitMessageViewVerticalLineLength @"PBCommitMessageViewVerticalLineLength"
@@ -25,6 +26,7 @@
#define kOpenPreviousDocumentsOnLaunch @"PBOpenPreviousDocumentsOnLaunch"
#define kPreviousDocumentPaths @"PBPreviousDocumentPaths"
#define kBranchFilterState @"PBBranchFilter"
#define kHistorySearchMode @"PBHistorySearchMode"
@implementation PBGitDefaults
@@ -53,6 +55,8 @@
forKey:kShouldCheckoutBranch];
[defaultValues setObject:[NSNumber numberWithBool:NO]
forKey:kOpenPreviousDocumentsOnLaunch];
[defaultValues setObject:[NSNumber numberWithInteger:kGitXBasicSeachMode]
forKey:kHistorySearchMode];
[[NSUserDefaults standardUserDefaults] registerDefaults:defaultValues];
}
@@ -170,4 +174,15 @@
[[NSUserDefaults standardUserDefaults] setInteger:state forKey:kBranchFilterState];
}
+ (NSInteger)historySearchMode
{
return [[NSUserDefaults standardUserDefaults] integerForKey:kHistorySearchMode];
}
+ (void)setHistorySearchMode:(NSInteger)mode
{
[[NSUserDefaults standardUserDefaults] setInteger:mode forKey:kHistorySearchMode];
}
@end
+62 -8
View File
@@ -702,6 +702,15 @@
<int key="NSvFlags">266</int>
<object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSProgressIndicator" id="354339555">
<reference key="NSNextResponder" ref="428755155"/>
<int key="NSvFlags">-2147482359</int>
<object class="NSPSMatrix" key="NSDrawMatrix"/>
<string key="NSFrame">{{637, 3}, {16, 16}}</string>
<reference key="NSSuperview" ref="428755155"/>
<int key="NSpiFlags">20746</int>
<double key="NSMaxValue">100</double>
</object>
<object class="NSSearchField" id="354285291">
<reference key="NSNextResponder" ref="428755155"/>
<int key="NSvFlags">265</int>
@@ -2096,6 +2105,14 @@
</object>
<int key="connectionID">437</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">progressIndicator</string>
<reference key="source" ref="596748029"/>
<reference key="destination" ref="354339555"/>
</object>
<int key="connectionID">448</int>
</object>
</object>
<object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects">
@@ -2439,6 +2456,7 @@
<reference ref="627778713"/>
<reference ref="354285291"/>
<reference ref="563692607"/>
<reference ref="354339555"/>
</object>
<reference key="parent" ref="24227530"/>
<string key="objectName">Commits Scope Bar</string>
@@ -2695,6 +2713,11 @@
<reference key="object" ref="349876124"/>
<reference key="parent" ref="627778713"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">447</int>
<reference key="object" ref="354339555"/>
<reference key="parent" ref="428755155"/>
</object>
</object>
</object>
<object class="NSMutableDictionary" key="flattenedProperties">
@@ -2803,6 +2826,7 @@
<string>428.IBSegmentedControlInspectorSelectedSegmentMetadataKey</string>
<string>430.IBPluginDependency</string>
<string>431.IBPluginDependency</string>
<string>447.IBPluginDependency</string>
<string>46.IBEditorWindowLastContentRect</string>
<string>46.IBPluginDependency</string>
<string>48.IBPluginDependency</string>
@@ -2987,6 +3011,7 @@
<integer value="0"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>{{9, 486}, {852, 432}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
@@ -3023,7 +3048,7 @@
</object>
</object>
<nil key="sourceID"/>
<int key="maxID">437</int>
<int key="maxID">448</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
@@ -3480,6 +3505,9 @@
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>selectBasicSearch:</string>
<string>selectPickaxeSearch:</string>
<string>selectRegexSearch:</string>
<string>stepperPressed:</string>
<string>updateSearch:</string>
</object>
@@ -3487,17 +3515,35 @@
<bool key="EncodedWithXMLCoder">YES</bool>
<string>id</string>
<string>id</string>
<string>id</string>
<string>id</string>
<string>id</string>
</object>
</object>
<object class="NSMutableDictionary" key="actionInfosByName">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>selectBasicSearch:</string>
<string>selectPickaxeSearch:</string>
<string>selectRegexSearch:</string>
<string>stepperPressed:</string>
<string>updateSearch:</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBActionInfo">
<string key="name">selectBasicSearch:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo">
<string key="name">selectPickaxeSearch:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo">
<string key="name">selectRegexSearch:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo">
<string key="name">stepperPressed:</string>
<string key="candidateClassName">id</string>
@@ -3515,6 +3561,7 @@
<string>commitController</string>
<string>historyController</string>
<string>numberOfMatchesField</string>
<string>progressIndicator</string>
<string>searchField</string>
<string>stepper</string>
</object>
@@ -3523,6 +3570,7 @@
<string>NSArrayController</string>
<string>PBGitHistoryController</string>
<string>NSTextField</string>
<string>NSProgressIndicator</string>
<string>NSSearchField</string>
<string>NSSegmentedControl</string>
</object>
@@ -3534,6 +3582,7 @@
<string>commitController</string>
<string>historyController</string>
<string>numberOfMatchesField</string>
<string>progressIndicator</string>
<string>searchField</string>
<string>stepper</string>
</object>
@@ -3551,6 +3600,10 @@
<string key="name">numberOfMatchesField</string>
<string key="candidateClassName">NSTextField</string>
</object>
<object class="IBToOneOutletInfo">
<string key="name">progressIndicator</string>
<string key="candidateClassName">NSProgressIndicator</string>
</object>
<object class="IBToOneOutletInfo">
<string key="name">searchField</string>
<string key="candidateClassName">NSSearchField</string>
@@ -4360,13 +4413,6 @@
<string key="minorKey">QuartzCore.framework/Headers/CIImageProvider.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">ScriptingBridge.framework/Headers/SBApplication.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
@@ -4472,6 +4518,14 @@
<string key="minorKey">AppKit.framework/Headers/NSPopUpButton.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSProgressIndicator</string>
<string key="superclassName">NSView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">AppKit.framework/Headers/NSProgressIndicator.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSResponder</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
+17
View File
@@ -9,6 +9,13 @@
#import <Cocoa/Cocoa.h>
typedef enum historySearchModes {
kGitXBasicSeachMode = 1,
kGitXPickaxeSearchMode,
kGitXRegexSearchMode,
kGitXMaxSearchMode // always keep this item last
} PBHistorySearchMode;
@class PBGitHistoryController;
@@ -16,11 +23,16 @@
PBGitHistoryController *historyController;
NSArrayController *commitController;
PBHistorySearchMode searchMode;
NSIndexSet *results;
NSSearchField *searchField;
NSSegmentedControl *stepper;
NSTextField *numberOfMatchesField;
NSProgressIndicator *progressIndicator;
NSTimer *searchTimer;
NSTask *backgroundSearchTask;
NSPanel *rewindPanel;
}
@@ -31,11 +43,16 @@
@property (assign) IBOutlet NSSearchField *searchField;
@property (assign) IBOutlet NSSegmentedControl *stepper;
@property (assign) IBOutlet NSTextField *numberOfMatchesField;
@property (assign) IBOutlet NSProgressIndicator *progressIndicator;
@property (assign) PBHistorySearchMode searchMode;
- (BOOL)isRowInSearchResults:(NSInteger)rowIndex;
- (BOOL)hasSearchResults;
- (void)selectSearchMode:(id)sender;
- (void)selectNextResult;
- (void)selectPreviousResult;
- (IBAction)stepperPressed:(id)sender;
+170 -2
View File
@@ -9,6 +9,7 @@
#import "PBHistorySearchController.h"
#import "PBGitHistoryController.h"
#import "PBGitRepository.h"
#import "PBGitDefaults.h"
#import <QuartzCore/CoreAnimation.h>
@@ -20,6 +21,8 @@
- (void)setupSearchMenuTemplate;
- (void)startBasicSearch;
- (void)startBackgroundSearch;
- (void)clearProgressIndicator;
- (void)showSearchRewindPanelReverse:(BOOL)isReversed;
@@ -30,6 +33,8 @@
#define kGitXSearchDirectionPrevious -1
#define kGitXBasicSearchLabel @"Subject, Author, SHA"
#define kGitXPickaxeSearchLabel @"Commit (pickaxe)"
#define kGitXRegexSearchLabel @"Commit (pickaxe regex)"
#define kGitXSearchArrangedObjectsContext @"GitXSearchArrangedObjectsContext"
@@ -42,6 +47,9 @@
@synthesize searchField;
@synthesize stepper;
@synthesize numberOfMatchesField;
@synthesize progressIndicator;
@synthesize searchMode;
@@ -58,6 +66,12 @@
return ([results count] > 0);
}
- (void)selectSearchMode:(id)sender
{
self.searchMode = [sender tag];
[self updateSearch:self];
}
- (void)selectNextResult
{
[self selectNextResultInDirection:kGitXSearchDirectionNext];
@@ -90,13 +104,16 @@
- (IBAction)updateSearch:(id)sender
{
[self startBasicSearch];
if (self.searchMode == kGitXBasicSeachMode)
[self startBasicSearch];
else
[self startBackgroundSearch];
}
- (void)awakeFromNib
{
[self setupSearchMenuTemplate];
[[searchField cell] setPlaceholderString:@"Subject, Author, SHA"];
self.searchMode = [PBGitDefaults historySearchMode];
[self updateUI];
@@ -181,6 +198,7 @@
[stepper setHidden:NO];
[historyController.commitList reloadData];
}
[self clearProgressIndicator];
}
// changes the selection to the next match after the current selected row unless the current row is already a match
@@ -203,6 +221,24 @@
NSMenu *searchMenu = [[NSMenu alloc] initWithTitle:@"Search Menu"];
NSMenuItem *item;
item = [[NSMenuItem alloc] initWithTitle:kGitXBasicSearchLabel action:@selector(selectSearchMode:) keyEquivalent:@""];
[item setTarget:self];
[item setTag:kGitXBasicSeachMode];
[searchMenu addItem:item];
item = [[NSMenuItem alloc] initWithTitle:kGitXPickaxeSearchLabel action:@selector(selectSearchMode:) keyEquivalent:@""];
[item setTarget:self];
[item setTag:kGitXPickaxeSearchMode];
[searchMenu addItem:item];
item = [[NSMenuItem alloc] initWithTitle:kGitXRegexSearchLabel action:@selector(selectSearchMode:) keyEquivalent:@""];
[item setTarget:self];
[item setTag:kGitXRegexSearchMode];
[searchMenu addItem:item];
item = [NSMenuItem separatorItem];
[searchMenu addItem:item];
item = [[NSMenuItem alloc] initWithTitle:@"Recent Searches" action:NULL keyEquivalent:@""];
[item setTag:NSSearchFieldRecentsTitleMenuItemTag];
[searchMenu addItem:item];
@@ -226,6 +262,77 @@
[[searchField cell] setSearchMenuTemplate:searchMenu];
}
- (void)updateSearchMenuState
{
NSMenu *searchMenu = [[searchField cell] searchMenuTemplate];
if (!searchMenu)
return;
NSMenuItem *item;
item = [searchMenu itemWithTag:kGitXBasicSeachMode];
[item setState:(searchMode == kGitXBasicSeachMode) ? NSOnState : NSOffState];
item = [searchMenu itemWithTag:kGitXPickaxeSearchMode];
[item setState:(searchMode == kGitXPickaxeSearchMode) ? NSOnState : NSOffState];
item = [searchMenu itemWithTag:kGitXRegexSearchMode];
[item setState:(searchMode == kGitXRegexSearchMode) ? NSOnState : NSOffState];
[[searchField cell] setSearchMenuTemplate:searchMenu];
[PBGitDefaults setHistorySearchMode:searchMode];
}
- (void)updateSearchPlaceholderString
{
switch (self.searchMode) {
case kGitXPickaxeSearchMode:
[[searchField cell] setPlaceholderString:kGitXPickaxeSearchLabel];
break;
case kGitXRegexSearchMode:
[[searchField cell] setPlaceholderString:kGitXRegexSearchLabel];
break;
default:
[[searchField cell] setPlaceholderString:kGitXBasicSearchLabel];
break;
}
}
- (void)setSearchMode:(PBHistorySearchMode)mode
{
if ((mode < kGitXBasicSeachMode) || (mode >= kGitXMaxSearchMode))
mode = kGitXBasicSeachMode;
searchMode = mode;
[PBGitDefaults setHistorySearchMode:searchMode];
[self updateSearchMenuState];
[self updateSearchPlaceholderString];
}
- (void)searchTimerFired:(NSTimer*)theTimer
{
[self.progressIndicator setHidden:NO];
[self.progressIndicator startAnimation:self];
}
- (void)clearProgressIndicator
{
[searchTimer invalidate];
searchTimer = nil;
[self.progressIndicator setHidden:YES];
[self.progressIndicator stopAnimation:self];
}
- (void)startProgressIndicator
{
[self clearProgressIndicator];
[numberOfMatchesField setHidden:YES];
[stepper setHidden:YES];
searchTimer = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:@selector(searchTimerFired:) userInfo:nil repeats:NO];
}
#pragma mark Basic Search
@@ -255,6 +362,67 @@
#pragma mark Pickaxe/Regex Search
- (void)startBackgroundSearch
{
if (backgroundSearchTask) {
NSFileHandle *handle = [[backgroundSearchTask standardOutput] fileHandleForReading];
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSFileHandleReadToEndOfFileCompletionNotification object:handle];
[backgroundSearchTask terminate];
}
NSString *searchString = [[searchField stringValue] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if ([searchString isEqualToString:@""]) {
[self clearSearch];
return;
}
results = nil;
NSMutableArray *searchArguments = [NSMutableArray arrayWithObjects:@"log", @"--pretty=format:%H", [NSString stringWithFormat:@"-S%@", searchString], nil];
if (self.searchMode == kGitXRegexSearchMode)
[searchArguments insertObject:@"--pickaxe-regex" atIndex:1];
backgroundSearchTask = [PBEasyPipe taskForCommand:[PBGitBinary path] withArgs:searchArguments inDir:[[historyController.repository fileURL] path]];
[backgroundSearchTask launch];
NSFileHandle *handle = [[backgroundSearchTask standardOutput] fileHandleForReading];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(parseBackgroundSearchResults:) name:NSFileHandleReadToEndOfFileCompletionNotification object:handle];
[handle readToEndOfFileInBackgroundAndNotify];
[self startProgressIndicator];
}
- (void)parseBackgroundSearchResults:(NSNotification *)notification
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSFileHandleReadToEndOfFileCompletionNotification object:[notification object]];
backgroundSearchTask = nil;
NSMutableIndexSet *indexes = [NSMutableIndexSet indexSet];
NSData *data = [[notification userInfo] valueForKey:NSFileHandleNotificationDataItem];
NSString *resultsString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSArray *resultsArray = [resultsString componentsSeparatedByString:@"\n"];
for (NSString *resultSHA in resultsArray) {
NSUInteger index = 0;
for (PBGitCommit *commit in [commitController arrangedObjects]) {
if ([resultSHA isEqualToString:commit.sha.string]) {
[indexes addIndex:index];
break;
}
index++;
}
}
results = indexes;
[self clearProgressIndicator];
[self updateSelectedResult];
}
#pragma mark -
#pragma mark Rewind Panel