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

process path directly from the input bar #44

Open
wants to merge 2 commits 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
119 changes: 102 additions & 17 deletions SDAppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -192,34 +192,76 @@ @implementation SDAppDelegate
/* Starting the app */
/******************************************************************************/

- (void) applicationDidFinishLaunching:(NSNotification *)notification {
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
NSArray* inputItems = [self getInputItems];
// NSLog(@"%ld", [inputItems count]);
// NSLog(@"%@", inputItems);

if ([inputItems count] < 1)
if ([inputItems count] < 1) {
[self cancel];
}

[NSApp activateIgnoringOtherApps: YES];
[NSApp activateIgnoringOtherApps:YES];

self.choices = [self choicesFromInputItems: inputItems];
self.choices = [self choicesFromInputItems:inputItems];

NSRect winRect, textRect, dividerRect, listRect;
[self getFrameForWindow: &winRect queryField: &textRect divider: &dividerRect tableView: &listRect];
[self getFrameForWindow:&winRect queryField:&textRect divider:&dividerRect tableView:&listRect];

[self setupWindow: winRect];
[self setupQueryField: textRect];
[self setupDivider: dividerRect];
[self setupResultsTable: listRect];
[self runQuery: @""];
[self setupWindow:winRect];
[self setupQueryField:textRect];
[self setupDivider:dividerRect];
[self setupResultsTable:listRect];
[self runQuery:@""];
[self resizeWindow];
[self.window center];
[self.window makeKeyAndOrderFront: nil];
[self.window makeKeyAndOrderFront:nil];

// Setup menu for copy and paste support
NSMenu *mainMenu = [[NSMenu alloc] initWithTitle:@"MainMenu"];
NSMenuItem *editMenuItem = [[NSMenuItem alloc] initWithTitle:@"Edit" action:nil keyEquivalent:@""];
[mainMenu addItem:editMenuItem];
NSMenu *editMenu = [[NSMenu alloc] initWithTitle:@"Edit"];
[editMenuItem setSubmenu:editMenu];

// Add copy action
NSMenuItem *copyItem = [[NSMenuItem alloc] initWithTitle:@"Copy"
action:@selector(copy:)
keyEquivalent:@"c"];
[copyItem setKeyEquivalentModifierMask:NSEventModifierFlagCommand];
[editMenu addItem:copyItem];

// Add paste action
NSMenuItem *pasteItem = [[NSMenuItem alloc] initWithTitle:@"Paste"
action:@selector(paste:)
keyEquivalent:@"v"];
[pasteItem setKeyEquivalentModifierMask:NSEventModifierFlagCommand];
[editMenu addItem:pasteItem];

[NSApp setMainMenu:mainMenu];

// these even work inside NSAlert, so start them later
[self setupKeyboardShortcuts];
}

/******************************************************************************/
/* Copy/Paste action to support Command + V */
/******************************************************************************/

- (void)paste:(id)sender {
// Ensure the query field is the first responder so it can receive the paste action
if ([self.queryField acceptsFirstResponder]) {
[self.queryField becomeFirstResponder];
[[self.queryField currentEditor] paste:nil];
}
}

- (void)copy:(id)sender {
// Ensure the query field is the first responder so it can respond to the copy action
if ([self.queryField acceptsFirstResponder]) {
[self.queryField becomeFirstResponder];
[[self.queryField currentEditor] copy:nil];
}
}


/******************************************************************************/
/* Setting up GUI elements */
/******************************************************************************/
Expand Down Expand Up @@ -463,6 +505,23 @@ - (void) runQuery:(NSString*)query {
/******************************************************************************/

- (void) choose {
NSString *inputText = [self.queryField stringValue];

// Check if the input is a valid path (file or directory)
BOOL isDir;
BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:inputText isDirectory:&isDir];

if (exists) {
if (isDir) {
// If it's a directory, open it in Finder
[[NSWorkspace sharedWorkspace] openFile:inputText];
} else {
// If it's a file, open it with the default application
[[NSWorkspace sharedWorkspace] openFile:inputText];
}
exit(0);
}

if ([self.filteredSortedChoices count] == 0) {
if (SDReturnStringOnMismatch) {
[self writeOutput: [self.queryField stringValue]];
Expand Down Expand Up @@ -553,16 +612,42 @@ - (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBy
return YES;
}
else if (commandSelector == @selector(insertTab:)) {
[self.queryField setStringValue: [[self.filteredSortedChoices objectAtIndex: self.choice] raw]];
[[self.queryField currentEditor] setSelectedRange: NSMakeRange(self.queryField.stringValue.length, 0)];
// Path auto-completion with Tab
NSString *currentPath = [self.queryField stringValue];
NSString *expandedPath = [currentPath stringByExpandingTildeInPath];
NSError *error = nil;
NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[expandedPath stringByDeletingLastPathComponent] error:&error];

BOOL autoCompleted = NO;
if (!error && contents) {
NSString *lastComponent = [currentPath lastPathComponent];
for (NSString *item in contents) {
if ([item hasPrefix:lastComponent]) {
NSString *completedPath = [[expandedPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:item];
[self.queryField setStringValue:completedPath];
autoCompleted = YES;
break;
}
}
}

if (!autoCompleted) {
// If no auto-completion was possible, fallback to the original Tab functionality
[self.queryField setStringValue:[[self.filteredSortedChoices objectAtIndex:self.choice] raw]];
[[self.queryField currentEditor] setSelectedRange:NSMakeRange(self.queryField.stringValue.length, 0)];
}
return YES;
}
else if (commandSelector == @selector(deleteForward:)) {
if ([[self.queryField stringValue] length] == 0)
[self cancel];
}
else if (commandSelector == @selector(paste:)) {
// Handle paste with Ctrl + V
[textView paste: nil];
return YES;
}

// NSLog(@"[%@]", NSStringFromSelector(commandSelector));
return NO;
}

Expand Down
4 changes: 2 additions & 2 deletions choose.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@
94DDE04419F2AC4C001A3B2E /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Debug;
defaultConfigurationName = Release;
};
94DDE04519F2AC4C001A3B2E /* Build configuration list for PBXNativeTarget "choose" */ = {
isa = XCConfigurationList;
Expand All @@ -276,7 +276,7 @@
94DDE04719F2AC4C001A3B2E /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Debug;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
Expand Down
79 changes: 79 additions & 0 deletions choose.xcodeproj/xcshareddata/xcschemes/choose.xcscheme
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1610"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
buildArchitectures = "Automatic">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "94DDE03D19F2AC4C001A3B2E"
BuildableName = "choose"
BlueprintName = "choose"
ReferencedContainer = "container:choose.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"
viewDebuggingEnabled = "No">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "94DDE03D19F2AC4C001A3B2E"
BuildableName = "choose"
BlueprintName = "choose"
ReferencedContainer = "container:choose.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "94DDE03D19F2AC4C001A3B2E"
BuildableName = "choose"
BlueprintName = "choose"
ReferencedContainer = "container:choose.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>