aboutsummaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/SPAppController.m4
-rw-r--r--Source/SPBundleEditorController.h2
-rw-r--r--Source/SPBundleEditorController.m228
-rw-r--r--Source/SPConstants.h1
-rw-r--r--Source/SPConstants.m1
-rw-r--r--Source/SPStringAdditions.m34
6 files changed, 208 insertions, 62 deletions
diff --git a/Source/SPAppController.m b/Source/SPAppController.m
index 430587a0..2003a9e6 100644
--- a/Source/SPAppController.m
+++ b/Source/SPAppController.m
@@ -893,7 +893,7 @@
NSBeep();
if (cmdData) [cmdData release];
} else {
- if([cmdData objectForKey:SPBundleFileNameKey] && [[cmdData objectForKey:SPBundleFileNameKey] length] && [cmdData objectForKey:SPBundleFileScopeKey])
+ if((![cmdData objectForKey:SPBundleFileDisabledKey] || ![[cmdData objectForKey:SPBundleFileDisabledKey] intValue]) && [cmdData objectForKey:SPBundleFileNameKey] && [[cmdData objectForKey:SPBundleFileNameKey] length] && [cmdData objectForKey:SPBundleFileScopeKey])
{
NSArray *scopes = [[cmdData objectForKey:SPBundleFileScopeKey] componentsSeparatedByString:@" "];
@@ -924,7 +924,7 @@
mask = mask | NSCommandKeyMask;
if([theMods rangeOfString:@"~"].length)
mask = mask | NSAlternateKeyMask;
- if(![[theChar lowercaseString] isEqualToString:theChar])
+ if([theMods rangeOfString:@"$"].length)
mask = mask | NSShiftKeyMask;
for(NSString* scope in scopes)
[[bundleKeyEquivalents objectForKey:scope] setObject:[NSArray arrayWithObjects:[theChar lowercaseString],
diff --git a/Source/SPBundleEditorController.h b/Source/SPBundleEditorController.h
index 35a11ed6..90ed03f1 100644
--- a/Source/SPBundleEditorController.h
+++ b/Source/SPBundleEditorController.h
@@ -23,6 +23,7 @@
// More info at <http://code.google.com/p/sequel-pro/>
#import <Cocoa/Cocoa.h>
+#import <ShortcutRecorder/ShortcutRecorder.h>
@class SRRecorderControl;
@@ -84,6 +85,7 @@
- (IBAction)addCommandBundle:(id)sender;
- (IBAction)removeCommandBundle:(id)sender;
- (IBAction)revealCommandBundleInFinder:(id)sender;
+- (IBAction)saveBundle:(id)sender;
- (IBAction)showHelp:(id)sender;
- (IBAction)saveAndCloseWindow:(id)sender;
diff --git a/Source/SPBundleEditorController.m b/Source/SPBundleEditorController.m
index b7e31aee..21cedc6e 100644
--- a/Source/SPBundleEditorController.m
+++ b/Source/SPBundleEditorController.m
@@ -24,12 +24,15 @@
#import "SPBundleEditorController.h"
+
@interface SPBundleEditorController (PrivateAPI)
- (void)_updateInputPopupButton;
@end
+#pragma mark -
+
@implementation SPBundleEditorController
/**
@@ -82,6 +85,7 @@
- (void)awakeFromNib
{
+ // Init all needed menus
inputEditorScopePopUpMenu = [[NSMenu alloc] initWithTitle:@""];
inputInputFieldScopePopUpMenu = [[NSMenu alloc] initWithTitle:@""];
inputDataTableScopePopUpMenu = [[NSMenu alloc] initWithTitle:@""];
@@ -199,11 +203,12 @@
[inputNonePopUpMenu addItem:anItem];
[anItem release];
+ [keyEquivalentField setCanCaptureGlobalHotKeys:YES];
+
}
#pragma mark -
-
- (IBAction)inputPopupButtonChanged:(id)sender
{
@@ -349,7 +354,8 @@
[removeButton setEnabled:([commandsTableView numberOfSelectedRows] > 0)];
[[self window] makeFirstResponder:commandsTableView];
-
+ if([commandsTableView numberOfSelectedRows] > 0)
+ [commandsTableView editColumn:0 row:insertIndex withEvent:nil select:YES];
}
- (IBAction)removeCommandBundle:(id)sender
@@ -358,7 +364,7 @@
defaultButton:NSLocalizedString(@"Remove", @"remove button")
alternateButton:NSLocalizedString(@"Cancel", @"cancel button")
otherButton:nil
- informativeTextWithFormat:NSLocalizedString(@"Are you sure you want to remove all selected Bundles? This action cannot be undone.", @"remove all selected bundles informative message")];
+ informativeTextWithFormat:NSLocalizedString(@"Are you sure you want to move all selected Bundles to the Trash and remove them respectively?", @"move to trash and remove resp all selected bundles informative message")];
[alert setAlertStyle:NSCriticalAlertStyle];
@@ -370,13 +376,31 @@
[[buttons objectAtIndex:1] setKeyEquivalent:@"\r"];
[alert beginSheetModalForWindow:[self window] modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:@"removeSelectedBundles"];
+
}
- (IBAction)revealCommandBundleInFinder:(id)sender
{
+
if([commandsTableView numberOfSelectedRows] != 1) return;
+
[[NSWorkspace sharedWorkspace] selectFile:[NSString stringWithFormat:@"%@/%@.%@/%@",
bundlePath, [[commandBundleArray objectAtIndex:[commandsTableView selectedRow]] objectForKey:@"bundleName"], SPUserBundleFileExtension, SPBundleFileName] inFileViewerRootedAtPath:nil];
+
+}
+
+- (IBAction)saveBundle:(id)sender
+{
+ NSSavePanel *panel = [NSSavePanel savePanel];
+
+ [panel setRequiredFileType:SPUserBundleFileExtension];
+
+ [panel setExtensionHidden:NO];
+ [panel setAllowsOtherFileTypes:NO];
+ [panel setCanSelectHiddenExtension:YES];
+ [panel setCanCreateDirectories:YES];
+
+ [panel beginSheetForDirectory:nil file:[[commandBundleArray objectAtIndex:[commandsTableView selectedRow]] objectForKey:@"bundleName"] modalForWindow:[self window] modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:@"saveBundle"];
}
- (IBAction)showHelp:(id)sender
@@ -439,6 +463,7 @@
}
[commandBundleArray addObject:bundleCommand];
+
}
if (cmdData) [cmdData release];
}
@@ -456,9 +481,48 @@
// Commit all pending edits
if([commandBundleArrayController commitEditing]) {
- NSLog(@"%@", commandBundleArray);
- [[self window] performClose:self];
+
+ // Make the bundleNames unique since they represent folder names
+ NSMutableDictionary *allNames = [NSMutableDictionary dictionary];
+ NSInteger idx = 0;
+ for(id item in commandBundleArray) {
+ if([allNames objectForKey:[item objectForKey:@"bundleName"]]) {
+ NSInteger i = 0;
+ NSString *newName = [NSString stringWithFormat:@"%@_%ld", [item objectForKey:@"bundleName"], i++];
+ while([allNames objectForKey:newName]) {
+ newName = [NSString stringWithFormat:@"%@_%ld", [item objectForKey:@"bundleName"], i++];
+ if(i>100) {
+ return NO;
+ }
+ }
+ [[commandBundleArray objectAtIndex:idx] setObject:newName forKey:@"bundleName"];
+ } else {
+ [allNames setObject:@"" forKey:[item objectForKey:@"bundleName"]];
+ }
+ idx++;
+ }
+
+ BOOL closeMe = YES;
+ for(id item in commandBundleArray) {
+ if(![self saveBundle:item atPath:nil]) {
+ closeMe = NO;
+ NSAlert *alert = [NSAlert alertWithMessageText:[NSString stringWithFormat:NSLocalizedString(@"Error while saving “%@”.", @"error while saving “%@”"), [item objectForKey:@"bundleName"]]
+ defaultButton:NSLocalizedString(@"OK", @"OK button")
+ alternateButton:nil
+ otherButton:nil
+ informativeTextWithFormat:@""];
+
+ [alert setAlertStyle:NSCriticalAlertStyle];
+ [alert runModal];
+ break;
+ }
+ }
+ if(closeMe)
+ [[self window] performClose:self];
}
+
+ [[NSApp delegate] reloadBundles:self];
+
}
- (BOOL)saveBundle:(NSDictionary*)bundle atPath:(NSString*)aPath
@@ -525,6 +589,80 @@
}
+/**
+ * Sheet did end method
+ */
+- (void)sheetDidEnd:(id)sheet returnCode:(NSInteger)returnCode contextInfo:(NSString *)contextInfo
+{
+
+ // Order out current sheet to suppress overlapping of sheets
+ if ([sheet respondsToSelector:@selector(orderOut:)])
+ [sheet orderOut:nil];
+ else if ([sheet respondsToSelector:@selector(window)])
+ [[sheet window] orderOut:nil];
+
+ if([contextInfo isEqualToString:@"removeSelectedBundles"]) {
+ if (returnCode == NSAlertDefaultReturn) {
+ NSIndexSet *indexes = [commandsTableView selectedRowIndexes];
+
+ // get last index
+ NSUInteger currentIndex = [indexes lastIndex];
+
+ while (currentIndex != NSNotFound) {
+
+ // Move already installed Bundles to Trash
+ NSString *bundleName = [[commandBundleArray objectAtIndex:currentIndex] objectForKey:@"bundleName"];
+ NSString *thePath = [NSString stringWithFormat:@"%@/%@.%@", bundlePath, bundleName, SPUserBundleFileExtension];
+ if([[NSFileManager defaultManager] fileExistsAtPath:thePath isDirectory:nil]) {
+ NSError *error = nil;
+ NSString *trashDir = [NSHomeDirectory() stringByAppendingPathComponent:@".Trash"];
+
+ // Use a AppleScript script since NSWorkspace performFileOperation or NSFileManager moveItemAtPath
+ // have problems probably due access rights.
+ NSString *moveToTrahCommand = [NSString stringWithFormat:@"osascript -e 'tell application \"Finder\" to move (POSIX file \"%@\") to the trash'", thePath];
+ [moveToTrahCommand runBashCommandWithEnvironment:nil atCurrentDirectoryPath:nil error:&error];
+ if(error != nil) {
+ NSAlert *alert = [NSAlert alertWithMessageText:[NSString stringWithFormat:NSLocalizedString(@"Error while moving “%@” to Trash.", @"error while moving “%@” to trash"), thePath]
+ defaultButton:NSLocalizedString(@"OK", @"OK button")
+ alternateButton:nil
+ otherButton:nil
+ informativeTextWithFormat:[error localizedDescription]];
+
+ [alert setAlertStyle:NSCriticalAlertStyle];
+ [alert runModal];
+ break;
+ }
+ }
+ [commandBundleArray removeObjectAtIndex:currentIndex];
+ // get next index (beginning from the end)
+ currentIndex = [indexes indexLessThanIndex:currentIndex];
+ }
+
+ [commandBundleArrayController rearrangeObjects];
+ [commandsTableView reloadData];
+
+ // Set focus to table view to avoid an unstable state
+ [[self window] makeFirstResponder:commandsTableView];
+
+ [removeButton setEnabled:([commandsTableView numberOfSelectedRows] > 0)];
+ }
+ } else if([contextInfo isEqualToString:@"saveBundle"]) {
+ if (returnCode == NSOKButton) {
+ if(![self saveBundle:[commandBundleArray objectAtIndex:[commandsTableView selectedRow]] atPath:[sheet filename]]) {
+ NSAlert *alert = [NSAlert alertWithMessageText:NSLocalizedString(@"Error while saving the Bundle.", @"error while saving a Bundle")
+ defaultButton:NSLocalizedString(@"OK", @"OK button")
+ alternateButton:nil
+ otherButton:nil
+ informativeTextWithFormat:@""];
+
+ [alert setAlertStyle:NSCriticalAlertStyle];
+ [alert runModal];
+ }
+ }
+ }
+
+}
+
#pragma mark -
#pragma mark NSWindow delegate
@@ -561,7 +699,33 @@
}
#pragma mark -
-#pragma mark TableView datasource methods
+#pragma mark SRRecorderControl delegate
+
+- (void)shortcutRecorder:(SRRecorderControl *)aRecorder keyComboDidChange:(KeyCombo)newKeyCombo
+{
+
+ if([commandsTableView selectedRow] < 0 || [commandsTableView selectedRow] > [commandBundleArray count]) return;
+
+ // Transform KeyCombo struct to KeyBinding.dict format for NSMenuItems
+ NSMutableString *keyEq = [NSMutableString string];
+ [keyEq setString:@""];
+ if(newKeyCombo.code > -1) {
+ if(newKeyCombo.flags & NSControlKeyMask)
+ [keyEq appendString:@"^"];
+ if(newKeyCombo.flags & NSAlternateKeyMask)
+ [keyEq appendString:@"~"];
+ if(newKeyCombo.flags & NSShiftKeyMask)
+ [keyEq appendString:@"$"];
+ if(newKeyCombo.flags & NSCommandKeyMask)
+ [keyEq appendString:@"@"];
+ [keyEq appendString:[aRecorder keyCharsIgnoringModifiers]];
+ }
+ [[commandBundleArray objectAtIndex:[commandsTableView selectedRow]] setObject:keyEq forKey:SPBundleFileKeyEquivalentKey];
+
+}
+
+#pragma mark -
+#pragma mark TableView data source and delegate
/**
* Returns the number of query commandBundleArray.
@@ -604,10 +768,13 @@
*/
- (void)controlTextDidEndEditing:(NSNotification *)aNotification
{
+
if([aNotification object] != commandsTableView) return;
NSString *newBundleName = [[[aNotification userInfo] objectForKey:@"NSFieldEditor"] string];
+ NSInteger selectedTableRow = [commandsTableView selectedRow];
+
BOOL isValid = YES;
if(newBundleName && [newBundleName length] && ![newBundleName rangeOfString:@"/"].length) {
@@ -634,9 +801,11 @@
}
// If not valid reset name to the old one
- if(!isValid)
- [[commandBundleArray objectAtIndex:[commandsTableView selectedRow]] setObject:oldBundleName forKey:@"bundleName"];
-
+ if(!isValid) {
+ if(!oldBundleName) oldBundleName = @"New Name";
+ [[commandBundleArray objectAtIndex:selectedTableRow] setObject:oldBundleName forKey:@"bundleName"];
+ }
+
[commandsTableView reloadData];
isTableCellEditing = NO;
@@ -644,39 +813,6 @@
}
#pragma mark -
-
-/**
- * Sheet did end method
- */
-- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(NSString *)contextInfo
-{
-
- if([contextInfo isEqualToString:@"removeSelectedBundles"]) {
- if (returnCode == NSAlertDefaultReturn) {
- NSIndexSet *indexes = [commandsTableView selectedRowIndexes];
-
- // get last index
- NSUInteger currentIndex = [indexes lastIndex];
-
- while (currentIndex != NSNotFound) {
- [commandBundleArray removeObjectAtIndex:currentIndex];
- // get next index (beginning from the end)
- currentIndex = [indexes indexLessThanIndex:currentIndex];
- }
-
- [commandBundleArrayController rearrangeObjects];
- [commandsTableView reloadData];
-
- // Set focus to table view to avoid an unstable state
- [[self window] makeFirstResponder:commandsTableView];
-
- [removeButton setEnabled:([commandsTableView numberOfSelectedRows] > 0)];
- }
- }
-
-}
-
-#pragma mark -
#pragma mark Menu validation
/**
@@ -685,10 +821,14 @@
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem
{
+ // Allow to record short-cuts used by the Bundle Editor
+ if([[NSApp mainWindow] firstResponder] == keyEquivalentField) return NO;
+
SEL action = [menuItem action];
if ( (action == @selector(duplicateCommandBundle:))
|| (action == @selector(revealCommandBundleInFinder:))
+ || (action == @selector(saveBundle:))
)
{
return ([commandsTableView numberOfSelectedRows] == 1);
@@ -770,6 +910,8 @@
@end
+#pragma mark -
+
@implementation SPBundleEditorController (PrivateAPI)
- (void)_updateInputPopupButton
@@ -777,6 +919,8 @@
NSInteger anIndex;
+ if([commandsTableView selectedRow] < 0 || [commandsTableView selectedRow] > [commandBundleArray count]) return;
+
NSDictionary *currentDict = [commandBundleArray objectAtIndex:[commandsTableView selectedRow]];
NSString *input = [currentDict objectForKey:SPBundleFileInputSourceKey];
diff --git a/Source/SPConstants.h b/Source/SPConstants.h
index 0284cfc8..d6544549 100644
--- a/Source/SPConstants.h
+++ b/Source/SPConstants.h
@@ -455,6 +455,7 @@ extern NSString *SPBundleFileInputSourceKey;
extern NSString *SPBundleFileInputSourceFallBackKey;
extern NSString *SPBundleFileOutputActionKey;
extern NSString *SPBundleFileKeyEquivalentKey;
+extern NSString *SPBundleFileInternalKeyEquivalentKey;
extern NSString *SPBundleFileTooltipKey;
extern NSString *SPBundleFileDisabledKey;
extern NSString *SPBundleInternLabelKey;
diff --git a/Source/SPConstants.m b/Source/SPConstants.m
index 12e46bfe..212f3add 100644
--- a/Source/SPConstants.m
+++ b/Source/SPConstants.m
@@ -274,6 +274,7 @@ NSString *SPBundleFileInputSourceKey = @"input";
NSString *SPBundleFileInputSourceFallBackKey = @"input_fallback";
NSString *SPBundleFileOutputActionKey = @"output";
NSString *SPBundleFileKeyEquivalentKey = @"keyEquivalent";
+NSString *SPBundleFileInternalKeyEquivalentKey = @"internalKeyEquivalent";
NSString *SPBundleFileTooltipKey = @"tooltip";
NSString *SPBundleFileDisabledKey = @"disabled";
NSString *SPBundleInternLabelKey = @"label";
diff --git a/Source/SPStringAdditions.m b/Source/SPStringAdditions.m
index 3198f2ff..4e2b114b 100644
--- a/Source/SPStringAdditions.m
+++ b/Source/SPStringAdditions.m
@@ -469,25 +469,23 @@
// Furthermore this id is used to communicate with the called command as file name.
NSString *processID = [NSString stringWithNewUUID];
[theEnv setObject:processID forKey:@"SP_PROCESS_ID"];
- id doc = [[[NSApp mainWindow] delegate] selectedTableDocument];
- if(!doc) {
- NSBeep();
- NSLog(@"No active document found for bash command.");
- return;
+ id doc = nil;
+ if([[[NSApp mainWindow] delegate] respondsToSelector:@selector(selectedTableDocument)])
+ doc = [[[NSApp mainWindow] delegate] selectedTableDocument];
+ if(doc != nil) {
+ [doc setProcessID:processID];
+
+ [theEnv setObject:[NSString stringWithFormat:@"%@%@", SPURLSchemeQueryInputPathHeader, processID] forKey:@"SP_QUERY_FILE_PATH"];
+ [theEnv setObject:[NSString stringWithFormat:@"%@%@", SPURLSchemeQueryResultPathHeader, processID] forKey:@"SP_QUERY_RESULT_FILE_PATH"];
+ [theEnv setObject:[NSString stringWithFormat:@"%@%@", SPURLSchemeQueryResultStatusPathHeader, processID] forKey:@"SP_QUERY_RESULT_STATUS_FILE_PATH"];
+ [theEnv setObject:[NSString stringWithFormat:@"%@%@", SPURLSchemeQueryResultMetaPathHeader, processID] forKey:@"SP_QUERY_RESULT_META_FILE_PATH"];
+
+ if([doc shellVariables])
+ [theEnv addEntriesFromDictionary:[doc shellVariables]];
+
+ if(theEnv != nil && [theEnv count])
+ [bashTask setEnvironment:theEnv];
}
- [doc setProcessID:processID];
-
- [theEnv setObject:[NSString stringWithFormat:@"%@%@", SPURLSchemeQueryInputPathHeader, processID] forKey:@"SP_QUERY_FILE_PATH"];
- [theEnv setObject:[NSString stringWithFormat:@"%@%@", SPURLSchemeQueryResultPathHeader, processID] forKey:@"SP_QUERY_RESULT_FILE_PATH"];
- [theEnv setObject:[NSString stringWithFormat:@"%@%@", SPURLSchemeQueryResultStatusPathHeader, processID] forKey:@"SP_QUERY_RESULT_STATUS_FILE_PATH"];
- [theEnv setObject:[NSString stringWithFormat:@"%@%@", SPURLSchemeQueryResultMetaPathHeader, processID] forKey:@"SP_QUERY_RESULT_META_FILE_PATH"];
-
- if([doc shellVariables])
- [theEnv addEntriesFromDictionary:[doc shellVariables]];
-
- if(theEnv != nil && [theEnv count])
- [bashTask setEnvironment:theEnv];
-
if(path != nil)
[bashTask setCurrentDirectoryPath:path];
else if([shellEnvironment objectForKey:@"SP_BUNDLE_PATH"] && [[NSFileManager defaultManager] fileExistsAtPath:[shellEnvironment objectForKey:@"SP_BUNDLE_PATH"] isDirectory:&isDir] && isDir)