Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spotlight #261

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
203 changes: 201 additions & 2 deletions Shuttle.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions Shuttle/AppDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@
NSMutableArray* ignoreHosts;
NSMutableArray* ignoreKeywords;

//Dictionary to hold all Leafs for indexing
NSMutableDictionary *spotlightIndex;

LaunchAtLoginController *launchAtLoginController;

}
Expand Down
108 changes: 87 additions & 21 deletions Shuttle/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,46 @@

#import "AppDelegate.h"
#import "AboutWindowController.h"
#import <CoreSpotlight/CoreSpotlight.h>

@implementation AppDelegate

- (BOOL)application:(NSApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<NSUserActivityRestoring>> * _Nonnull))restorationHandler {
NSArray *objectsFromJSON = [userActivity.userInfo[@"kCSSearchableItemActivityIdentifier"] componentsSeparatedByString:(@"¬_¬")];

[self openHost:objectsFromJSON];

return YES;
}

- (void)indexForSpotlight {
[[CSSearchableIndex defaultSearchableIndex] deleteSearchableItemsWithDomainIdentifiers:[NSArray arrayWithObjects: @"spotlight.shuttle", nil] completionHandler:^(NSError * _Nullable error) {

NSMutableArray *items = [[NSMutableArray alloc]init];

for(id key in self->spotlightIndex){

NSDictionary *cfg = [self->spotlightIndex objectForKey:key];

CSSearchableItemAttributeSet *attributeSet = [[CSSearchableItemAttributeSet alloc] initWithItemContentType:(NSString*)kUTTypeApplication];

attributeSet.title = [NSString stringWithFormat:@"%@", cfg[@"title"]];
attributeSet.contentDescription = [NSString stringWithFormat:@"%@", cfg[@"cmd"]];

CSSearchableItem *item = [[CSSearchableItem alloc] initWithUniqueIdentifier:key domainIdentifier:@"spotlight.shuttle" attributeSet:attributeSet];

[items addObject:item];
}

[[CSSearchableIndex defaultSearchableIndex] indexSearchableItems:items completionHandler:^(NSError * __nullable error){
if(error){
NSLog(@"Indexing failed: %@", error);
return;
}
}];
}];
}

- (void) awakeFromNib {

// The location for the JSON path file. This is a simple file that contains the hard path to the *.json settings file.
Expand Down Expand Up @@ -89,13 +126,13 @@ - (void) awakeFromNib {
launchAtLoginController = [[LaunchAtLoginController alloc] init];
// Needed to trigger the menuWillOpen event
[menu setDelegate:self];

[self refresh];
}

- (BOOL) needUpdateFor: (NSString*) file with: (NSDate*) old {

if (![[NSFileManager defaultManager] fileExistsAtPath:[file stringByExpandingTildeInPath]])
return false;

if (old == NULL)
return true;

Expand All @@ -109,7 +146,7 @@ - (NSDate*) getMTimeFor: (NSString*) file {
return [attributes fileModificationDate];
}

- (void)menuWillOpen:(NSMenu *)menu {
- (void)refresh {
// Check when the config was last modified
if ( [self needUpdateFor:shuttleConfigFile with:configModified] ||
[self needUpdateFor:shuttleAltConfigFile with:configModified2] ||
Expand All @@ -118,13 +155,21 @@ - (void)menuWillOpen:(NSMenu *)menu {

configModified = [self getMTimeFor:shuttleConfigFile];
configModified2 = [self getMTimeFor:shuttleAltConfigFile];
sshConfigSystem = [self getMTimeFor: @"/etc/ssh_config"];
sshConfigSystem = [self getMTimeFor: @"/etc/ssh/ssh_config"];
sshConfigUser = [self getMTimeFor: @"~/.ssh/config"];

spotlightIndex = [[NSMutableDictionary alloc] init];

[self loadMenu];

[self indexForSpotlight];
}
}

- (void)menuWillOpen:(NSMenu *)menu {
[self refresh];
}

// Parsing of the SSH Config File
// Courtesy of https://gist.github.com/geeksunny/3376694
- (NSDictionary<NSString *, NSDictionary *> *)parseSSHConfigFile {
Expand Down Expand Up @@ -194,8 +239,8 @@ - (void)menuWillOpen:(NSMenu *)menu {
if ([first isEqualToString:@"Include"]) {
// Support for ssh_config Include directive.
NSString *includePath = ([second isAbsolutePath])
? [second stringByExpandingTildeInPath]
: [[filepath stringByDeletingLastPathComponent] stringByAppendingPathComponent:second];
? [second stringByExpandingTildeInPath]
: [[filepath stringByDeletingLastPathComponent] stringByAppendingPathComponent:second];

[servers addEntriesFromDictionary:[self parseSSHConfig:includePath]];
}
Expand Down Expand Up @@ -418,9 +463,13 @@ - (void) buildMenu:(NSArray*)data addToMenu:(NSMenu *)m {
//Place the terminal command, theme, and title into an comma delimited string
NSString *menuRepObj = [NSString stringWithFormat:@"%@¬_¬%@¬_¬%@¬_¬%@¬_¬%@", menuCmd, termTheme, termTitle, termWindow, menuName];

spotlightIndex[menuRepObj] = cfg;

//[self indexTitle: termTitle command: menuCmd theme: termTheme window:termWindow name: menuName menuRepObj: menuRepObj];

[menuItem setTitle:menuName];
[menuItem setRepresentedObject:menuRepObj];
[menuItem setAction:@selector(openHost:)];
[menuItem setAction:@selector(openHostFromMenu:)];
[m insertItem:menuItem atIndex:pos++];
if (addSeparator) {
[m insertItem:[NSMenuItem separatorItem] atIndex:pos++];
Expand Down Expand Up @@ -463,7 +512,7 @@ - (void) separatorSortRemoval:(NSString *)currentName {
}
}

- (void) openHost:(NSMenuItem *) sender {
- (void) openHost:(NSArray *) objectsFromJSON {
//NSLog(@"sender: %@", sender);
//NSLog(@"Command: %@",[sender representedObject]);

Expand All @@ -472,7 +521,7 @@ - (void) openHost:(NSMenuItem *) sender {


//Place the comma delimited string of menu item settings into an array
NSArray *objectsFromJSON = [[sender representedObject] componentsSeparatedByString:(@"¬_¬")];
//NSArray *objectsFromJSON = [[sender representedObject] componentsSeparatedByString:(@"¬_¬")];

//This is our command that will be run in the terminal window
NSString *escapedObject;
Expand Down Expand Up @@ -565,10 +614,10 @@ - (void) openHost:(NSMenuItem *) sender {
}
// Check if Url
if (url)
{
[[NSWorkspace sharedWorkspace] openURL:url];
}
{
[[NSWorkspace sharedWorkspace] openURL:url];

}
//If the JSON file is set to use iTerm
else if ( [terminalPref rangeOfString: @"iterm"].location !=NSNotFound ) {

Expand Down Expand Up @@ -649,6 +698,13 @@ - (void) openHost:(NSMenuItem *) sender {
}
}

- (void) openHostFromMenu:(NSMenuItem *) sender {

NSArray *objectsFromJSON = [[sender representedObject] componentsSeparatedByString:(@"¬_¬")];

[self openHost:objectsFromJSON];
}

- (void) runScript:(NSString *)scriptPath handler:(NSString*)handlerName parameters:(NSArray*)parametersInArray {
//special thanks to stackoverflow.com/users/316866/leandro for pointing me the right direction.
//see http://goo.gl/olcpaX
Expand Down Expand Up @@ -699,14 +755,24 @@ - (void) runScript:(NSString *)scriptPath handler:(NSString*)handlerName paramet

[containerEvent setParamDescriptor:arguments forKeyword:keyDirectObject];
}
NSDictionary * executionError = nil;
//Execute the event
[appleScript executeAppleEvent:containerEvent error:nil];
NSAppleEventDescriptor *result = [appleScript executeAppleEvent:containerEvent error:&executionError];

if (executionError != nil) {
NSLog(@"error while executing script. Error %@", executionError);

} else {
NSLog(@"Script execution has succeed. Result(%@)", result);

}

}
}

- (IBAction)showImportPanel:(id)sender {
NSOpenPanel * openPanelObj = [NSOpenPanel openPanel];
NSInteger tvarNSInteger = [openPanelObj runModal];
NSOpenPanel * openPanelObj = [NSOpenPanel openPanel];
NSInteger tvarNSInteger = [openPanelObj runModal];
if(tvarNSInteger == NSOKButton){
//Backup the current configuration
[[NSFileManager defaultManager] moveItemAtPath:shuttleConfigFile toPath: [NSHomeDirectory() stringByAppendingPathComponent:@".shuttle.json.backup"] error: nil];
Expand Down Expand Up @@ -743,9 +809,9 @@ -(void) throwError:(NSString*)errorMessage additionalInfo:(NSString*)errorInfo c
}

- (IBAction)showExportPanel:(id)sender {
NSSavePanel * savePanelObj = [NSSavePanel savePanel];
NSSavePanel * savePanelObj = [NSSavePanel savePanel];
//Display the Save Panel
NSInteger result = [savePanelObj runModal];
NSInteger result = [savePanelObj runModal];
if (result == NSFileHandlingPanelOKButton) {
NSURL *saveURL = [savePanelObj URL];
// then copy a previous file to the new location
Expand All @@ -767,14 +833,14 @@ - (IBAction)configure:(id)sender {
//build the reprensented object. It's expecting menuCmd, termTheme, termTitle, termWindow, menuName
NSString *editorRepObj = [NSString stringWithFormat:@"%@¬_¬%@¬_¬%@¬_¬%@¬_¬%@", editorCommand, nil, @"Editing shuttle JSON", nil, nil];

//make a menu item for the command selector(openHost:) runs in a new terminal window.
NSMenuItem *editorMenu = [[NSMenuItem alloc] initWithTitle:@"editJSONconfig" action:@selector(openHost:) keyEquivalent:(@"")];
//make a menu item for the command selector(openHostFromMenu:) runs in a new terminal window.
NSMenuItem *editorMenu = [[NSMenuItem alloc] initWithTitle:@"editJSONconfig" action:@selector(openHostFromMenu:) keyEquivalent:(@"")];

//set the command for the menu item
[editorMenu setRepresentedObject:editorRepObj];

//open the JSON file in the terminal editor.
[self openHost:editorMenu];
[self openHostFromMenu:editorMenu];
}
}

Expand Down
67 changes: 67 additions & 0 deletions ShuttleSpotlightPreview/Base.lproj/PreviewViewController.xib
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14490.70"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="PreviewViewController">
<connections>
<outlet property="command" destination="mvc-m5-mN5" id="mVD-hT-wx0"/>
<outlet property="label" destination="dwJ-Sw-bY8" id="R7T-nd-giA"/>
<outlet property="view" destination="c22-O7-iKe" id="NRM-P4-wb6"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customView id="c22-O7-iKe" userLabel="Preview View">
<rect key="frame" x="0.0" y="0.0" width="483" height="272"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dwJ-Sw-bY8">
<rect key="frame" x="18" y="86" width="447" height="23"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" alignment="center" title="Fwa2-Loc1 (Managment Loc2)" id="EAk-4P-zx1">
<font key="font" metaFont="system" size="19"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="mvc-m5-mN5">
<rect key="frame" x="18" y="32" width="447" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" alignment="center" title="ssh -oKexAlgorithms=+diffie-hellman-group1-sha1 bob@10.201.248.254" id="ZCo-Rx-DbF">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="dpT-P5-EF1">
<rect key="frame" x="20" y="67" width="443" height="5"/>
</box>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="E3O-rN-Is7">
<rect key="frame" x="174" y="69" width="135" height="135"/>
<constraints>
<constraint firstAttribute="height" constant="135" id="1ee-Nu-Tfa"/>
<constraint firstAttribute="width" constant="135" id="UBO-4s-EMi"/>
</constraints>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="ShuttleImage" id="iVz-fB-HlN"/>
</imageView>
</subviews>
<constraints>
<constraint firstItem="mvc-m5-mN5" firstAttribute="leading" secondItem="c22-O7-iKe" secondAttribute="leading" constant="20" id="CeC-li-y11"/>
<constraint firstItem="E3O-rN-Is7" firstAttribute="centerY" secondItem="c22-O7-iKe" secondAttribute="centerY" id="L32-hT-x9J"/>
<constraint firstAttribute="trailing" secondItem="dpT-P5-EF1" secondAttribute="trailing" constant="20" id="VdT-0H-Vmp"/>
<constraint firstAttribute="trailing" secondItem="dwJ-Sw-bY8" secondAttribute="trailing" constant="20" id="Vzl-ra-a2g"/>
<constraint firstItem="E3O-rN-Is7" firstAttribute="centerX" secondItem="c22-O7-iKe" secondAttribute="centerX" id="YIM-9p-RaT"/>
<constraint firstItem="dpT-P5-EF1" firstAttribute="leading" secondItem="c22-O7-iKe" secondAttribute="leading" constant="20" id="alg-sl-iVE"/>
<constraint firstItem="dwJ-Sw-bY8" firstAttribute="leading" secondItem="c22-O7-iKe" secondAttribute="leading" constant="20" id="esK-hZ-lzO"/>
<constraint firstAttribute="trailing" secondItem="mvc-m5-mN5" secondAttribute="trailing" constant="20" id="h3g-iN-O5k"/>
<constraint firstItem="mvc-m5-mN5" firstAttribute="top" secondItem="dpT-P5-EF1" secondAttribute="bottom" constant="20" id="skg-2v-M1V"/>
<constraint firstAttribute="bottom" secondItem="mvc-m5-mN5" secondAttribute="bottom" constant="32" id="uXB-nv-vMH"/>
</constraints>
<point key="canvasLocation" x="138.5" y="154"/>
</customView>
</objects>
<resources>
<image name="ShuttleImage" width="256" height="256"/>
</resources>
</document>
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{
"images" : [
{
"size" : "16x16",
"idiom" : "mac",
"filename" : "shuttle16pt.png",
"scale" : "1x"
},
{
"size" : "16x16",
"idiom" : "mac",
"filename" : "shuttle16pt2x.png",
"scale" : "2x"
},
{
"size" : "32x32",
"idiom" : "mac",
"filename" : "shuttle32pt.png",
"scale" : "1x"
},
{
"size" : "32x32",
"idiom" : "mac",
"filename" : "shuttle32pt2x.png",
"scale" : "2x"
},
{
"size" : "128x128",
"idiom" : "mac",
"filename" : "shuttle128pt.png",
"scale" : "1x"
},
{
"size" : "128x128",
"idiom" : "mac",
"filename" : "shuttle128pt2x.png",
"scale" : "2x"
},
{
"size" : "256x256",
"idiom" : "mac",
"filename" : "shuttle256pt.png",
"scale" : "1x"
},
{
"size" : "256x256",
"idiom" : "mac",
"filename" : "shuttle256pt2x.png",
"scale" : "2x"
},
{
"size" : "512x512",
"idiom" : "mac",
"filename" : "shuttle512pt.png",
"scale" : "1x"
},
{
"size" : "512x512",
"idiom" : "mac",
"filename" : "shuttle512pt2x.png",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions ShuttleSpotlightPreview/Images.xcassets/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Loading