From 169fb3fffeff55cff32952a82adba055dfc050f9 Mon Sep 17 00:00:00 2001 From: Bibiko Date: Wed, 10 Nov 2010 12:00:59 +0000 Subject: =?UTF-8?q?=E2=80=A2=20first=20implementation=20=20to=20allow=20th?= =?UTF-8?q?e=20user=20to=20write=20and=20use=20self-definable=20functions?= =?UTF-8?q?=20inside=20the=20Custom=20Query=20Editor=20-=20such=20commands?= =?UTF-8?q?=20will=20be=20stored=20as=20foo.spBundle=20in=20SP's=20Applica?= =?UTF-8?q?tion=20Folder/Bundles=20-=20up=20to=20now=20they=20will=20be=20?= =?UTF-8?q?displayed=20inside=20the=20context=20menu=20as=20submenu=20Bund?= =?UTF-8?q?les=20which=20can=20be=20by=20itself=20contain=20further=20subm?= =?UTF-8?q?enus=20specified=20via=20'category'=20key=20-=20to=20each=20com?= =?UTF-8?q?mand=20the=20user=20can=20assign=20a=20tooltip=20and=20a=20keyb?= =?UTF-8?q?oard=20short-cut;=20if=20user=20chose=20a=20standard=20SP=20sho?= =?UTF-8?q?rt-cut=20it=20will=20be=20ignored=20-=20commands=20will=20be=20?= =?UTF-8?q?executed=20as=20bash=20commands=20ie=20it=20can=20also=20be=20w?= =?UTF-8?q?ritten=20in=20any=20script=20language=20-=20the=20bash=20proces?= =?UTF-8?q?s=20inherits=20several=20environment=20variables=20like=20SP=5F?= =?UTF-8?q?BUNDLE=5FPATH,=20SP=5FSELECTED=5FTEXT,=20SP=5FSELECTED=5FDATABA?= =?UTF-8?q?SE,=20SP=5FSELECTED=5FTABLE,=20SP=5FCURRENT=5FQUERY,=20SP=5FCUR?= =?UTF-8?q?RENT=5FLINE,=20SP=5FCURRENT=5FWORD=20-=20the=20bash=20command's?= =?UTF-8?q?=20result=20can=20be=20processed=20as=20follows:=20insertAsText?= =?UTF-8?q?,=20insertAsSnippet,=20replaceContent,=20replaceSeletion=20(wit?= =?UTF-8?q?h=20fallbacks=20to=20word,=20line,=20query,=20entire=20content)?= =?UTF-8?q?,=20showAsTextTooltip,=20showAsHTMLTooltip=20-=20up=20to=20now?= =?UTF-8?q?=20all=20installed=20bundles=20are=20reload=20for=20each=20menu?= =?UTF-8?q?ForEvent:=20[this=20is=20tendative!]=20-=20each=20spBundle=20co?= =?UTF-8?q?mmand=20has=20a=20scope=20to=20allow=20to=20the=20user=20to=20s?= =?UTF-8?q?pecify=20for=20which=20SP=20element=20a=20command=20can=20be=20?= =?UTF-8?q?useful;=20up=20to=20now=20only=20the=20scope=20'editor'=20is=20?= =?UTF-8?q?supported;=20further=20scopes=20could=20be=20'data=20table'=20f?= =?UTF-8?q?or=20context=20menus=20of=20mysql=20table=20data=20(Content=20o?= =?UTF-8?q?r=20Custom=20Query=20-=20including=20info=20of=20selected=20lin?= =?UTF-8?q?es,=20table=20data=20in=20different=20formats,=20etc.)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - foo.spBundle files can be installed simply by double-clicking at it (remember up to now Bundles will be reloaded while opening the editor's context menu!) two tiny examples for testing: http://wwwstaff.eva.mpg.de/~bibiko/dt/temp/spBundleExamples.zip --- Source/SPDatabaseDocument.m | 4 +- Source/SPTextView.m | 154 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 151 insertions(+), 7 deletions(-) diff --git a/Source/SPDatabaseDocument.m b/Source/SPDatabaseDocument.m index 75a16e73..f3f419d8 100644 --- a/Source/SPDatabaseDocument.m +++ b/Source/SPDatabaseDocument.m @@ -241,7 +241,9 @@ [taskProgressWindow setAlphaValue:0.0]; [taskProgressWindow setContentView:taskProgressLayer]; - [contentViewSplitter setDelegate:self]; + [[customQueryInstance valueForKeyPath:@"textView"] reloadBundleItems]; + + [contentViewSplitter setDelegate:self]; } /** diff --git a/Source/SPTextView.m b/Source/SPTextView.m index 32edf6f1..9de1d0af 100644 --- a/Source/SPTextView.m +++ b/Source/SPTextView.m @@ -2129,7 +2129,7 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse) if([bundleKeyEquivalents count]) { for(NSString* key in [bundleKeyEquivalents allKeys]) { NSArray *keyData = [bundleKeyEquivalents objectForKey:key]; - if([[keyData objectAtIndex:0] isEqualToString:charactersIgnMod] && [[[bundleKeyEquivalents objectForKey:key] objectAtIndex:1] intValue] & curFlags) { + if([[keyData objectAtIndex:0] isEqualToString:charactersIgnMod] && [[[bundleKeyEquivalents objectForKey:key] objectAtIndex:1] intValue] == curFlags) { NSMenuItem *item = [[[NSMenuItem alloc] init] autorelease]; [item setToolTip:[[bundleKeyEquivalents objectForKey:key] objectAtIndex:2]]; [item setTag:0]; @@ -3448,12 +3448,13 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse) if([cmdData objectForKey:@"keyEquivalent"] && [[cmdData objectForKey:@"keyEquivalent"] length]) { NSString *theKey = [cmdData objectForKey:@"keyEquivalent"]; NSString *theChar = [theKey substringFromIndex:[theKey length]-1]; + NSString *theMods = [theKey substringToIndex:[theKey length]-1]; NSUInteger mask = 0; - if([theKey rangeOfString:@"^"].length) + if([theMods rangeOfString:@"^"].length) mask = mask | NSControlKeyMask; - if([theKey rangeOfString:@"@"].length) + if([theMods rangeOfString:@"@"].length) mask = mask | NSCommandKeyMask; - if([theKey rangeOfString:@"~"].length) + if([theMods rangeOfString:@"~"].length) mask = mask | NSAlternateKeyMask; if(![[theChar lowercaseString] isEqualToString:theChar]) mask = mask | NSShiftKeyMask; @@ -3480,13 +3481,154 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse) - (IBAction)executeBundleItem:(id)sender { NSInteger idx = [sender tag] - 1000000; + NSString *infoPath = nil; if(idx >=0 && idx < [bundleItems count]) { - NSLog(@"%@", [[bundleItems objectAtIndex:idx] objectForKey:@"path"]); + infoPath = [[bundleItems objectAtIndex:idx] objectForKey:@"path"]; } else { if([sender tag] == 0 && [[sender toolTip] length]) { - NSLog(@"%@", [sender toolTip]); + infoPath = [sender toolTip]; } } + + if(!infoPath) { + NSBeep(); + return; + } + + NSError *readError = nil; + NSString *convError = nil; + NSPropertyListFormat format; + NSDictionary *cmdData = nil; + NSData *pData = [NSData dataWithContentsOfFile:infoPath options:NSUncachedRead error:&readError]; + + cmdData = [[NSPropertyListSerialization propertyListFromData:pData + mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&convError] retain]; + + if(!cmdData || readError != nil || [convError length] || !(format == NSPropertyListXMLFormat_v1_0 || format == NSPropertyListBinaryFormat_v1_0)) { + NSLog(@"“%@” file couldn't be read.", infoPath); + NSBeep(); + if (cmdData) [cmdData release]; + return; + } else { + if([cmdData objectForKey:@"command"] && [[cmdData objectForKey:@"command"] length]) { + + NSString *cmd = [cmdData objectForKey:@"command"]; + NSError *err = nil; + NSRange currentWordRange, currentQueryRange, currentSelectionRange, currentLineRange; + + NSMutableDictionary *env = [NSMutableDictionary dictionary]; + [env setObject:[infoPath stringByDeletingLastPathComponent] forKey:@"SP_BUNDLE_PATH"]; + + currentSelectionRange = [self selectedRange]; + if(currentSelectionRange.length) + [env setObject:[[self string] substringWithRange:currentSelectionRange] forKey:@"SP_SELECTED_TEXT"]; + + if (tablesListInstance && [tablesListInstance selectedDatabase]) + [env setObject:[tablesListInstance selectedDatabase] forKey:@"SP_SELECTED_DATABASE"]; + + if (tablesListInstance && [tablesListInstance tableName]) + [env setObject:[tablesListInstance tableName] forKey:@"SP_SELECTED_TABLE"]; + + + if(customQueryInstance && [customQueryInstance currentQueryRange].length) { + currentQueryRange = [customQueryInstance currentQueryRange]; + [env setObject:[[self string] substringWithRange:[customQueryInstance currentQueryRange]] forKey:@"SP_CURRENT_QUERY"]; + } else { + currentQueryRange = currentSelectionRange; + } + + currentWordRange = [self getRangeForCurrentWord]; + if(currentWordRange.length) + [env setObject:[[self string] substringWithRange:currentWordRange] forKey:@"SP_CURRENT_WORD"]; + + currentLineRange = [[self string] lineRangeForRange:NSMakeRange([self selectedRange].location, 0)]; + if(currentLineRange.length) + [env setObject:[[self string] substringWithRange:currentLineRange] forKey:@"SP_CURRENT_LINE"]; + + NSString *output = [cmd runBashCommandWithEnvironment:env atCurrentDirectoryPath:nil error:&err]; + + if(err == nil && [cmdData objectForKey:@"output"] && [[cmdData objectForKey:@"output"] length] && ![[cmdData objectForKey:@"output"] isEqualToString:@"nop"]) { + NSString *action = [[cmdData objectForKey:@"output"] lowercaseString]; + + if([action isEqualToString:@"insertastext"]) { + [self insertText:output]; + } + + else if([action isEqualToString:@"insertassnippet"]) { + NSString *inputAction = @""; + NSString *inputFallBackAction = @""; + if([cmdData objectForKey:@"input"]) + inputAction = [[cmdData objectForKey:@"input"] lowercaseString]; + if([cmdData objectForKey:@"input_fallback"]) + inputFallBackAction = [[cmdData objectForKey:@"input_fallback"] lowercaseString]; + NSRange replaceRange = NSMakeRange(currentSelectionRange.location, 0); + if([inputAction isEqualToString:@"selectedtext"]) { + if(!currentSelectionRange.length) { + if([inputFallBackAction isEqualToString:@"currentword"]) + replaceRange = currentWordRange; + else if([inputFallBackAction isEqualToString:@"currentline"]) + replaceRange = currentLineRange; + else if([inputFallBackAction isEqualToString:@"currentquery"]) + replaceRange = currentQueryRange; + else if([inputAction isEqualToString:@"entirecontent"]) + replaceRange = NSMakeRange(0,[[self string] length]); + } else { + replaceRange = currentSelectionRange; + } + } + [self insertAsSnippet:output atRange:replaceRange]; + } + + else if([action isEqualToString:@"replacecontent"]) { + if([[self string] length]) + [self setSelectedRange:NSMakeRange(0,[[self string] length])]; + [self insertText:output]; + } + + else if([action isEqualToString:@"replaceselection"]) { + NSString *inputAction = @""; + NSString *inputFallBackAction = @""; + if([cmdData objectForKey:@"input"]) + inputAction = [[cmdData objectForKey:@"input"] lowercaseString]; + if([cmdData objectForKey:@"input_fallback"]) + inputFallBackAction = [[cmdData objectForKey:@"input_fallback"] lowercaseString]; + NSRange replaceRange = NSMakeRange(currentSelectionRange.location, 0); + if([inputAction isEqualToString:@"selectedtext"]) { + if(!currentSelectionRange.length) { + if([inputFallBackAction isEqualToString:@"currentword"]) + replaceRange = currentWordRange; + else if([inputFallBackAction isEqualToString:@"currentline"]) + replaceRange = currentLineRange; + else if([inputFallBackAction isEqualToString:@"currentquery"]) + replaceRange = currentQueryRange; + else if([inputAction isEqualToString:@"entirecontent"]) + replaceRange = NSMakeRange(0,[[self string] length]); + } else { + replaceRange = currentSelectionRange; + } + } + [self shouldChangeTextInRange:replaceRange replacementString:output]; + [self replaceCharactersInRange:replaceRange withString:output]; + } + + else if([action isEqualToString:@"showastexttooltip"]) { + [SPTooltip showWithObject:output]; + } + + else if([action isEqualToString:@"showashtmltooltip"]) { + [SPTooltip showWithObject:output ofType:@"html"]; + } + + } else { + NSString *errorMessage = [err localizedDescription]; + SPBeginAlertSheet(NSLocalizedString(@"BASH Error", @"bash error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, [self window], self, nil, nil, + [NSString stringWithFormat:@"%@ “%@”:\n%@", NSLocalizedString(@"Error for", @"error for message"), [cmdData objectForKey:@"name"], errorMessage]); + } + } + + if (cmdData) [cmdData release]; + } + } #pragma mark - -- cgit v1.2.3