From 96d3ef381eda7771e5b197ca51323786a83c1528 Mon Sep 17 00:00:00 2001 From: 750 Date: Fri, 22 Nov 2024 01:26:16 +0300 Subject: [PATCH 1/4] #47 n1: customizable input separator --- SDAppDelegate.m | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/SDAppDelegate.m b/SDAppDelegate.m index 1cb467b..962e281 100644 --- a/SDAppDelegate.m +++ b/SDAppDelegate.m @@ -13,6 +13,7 @@ static NSFont* SDQueryFont; static NSString* PromptText; static NSString* InitialQuery; +static NSString* Separator; static int SDNumRows; static int SDPercentWidth; static BOOL SDUnderlineDisabled; @@ -644,7 +645,7 @@ - (NSArray*) getInputItems { if ([inputStrings length] == 0) return nil; - return [inputStrings componentsSeparatedByString:@"\n"]; + return [inputStrings componentsSeparatedByString: Separator]; #endif @@ -679,6 +680,10 @@ static void usage(const char* name) { printf(" -m return the query string in case it doesn't match any item\n"); printf(" -p defines a prompt to be displayed when query field is empty\n"); printf(" -q defines initial query to start with (empty by default)\n"); + printf(" -x defines separator string, a single newline (\\n) by default\n"); + printf(" beware of escaping:\n"); + printf(" passing -x \\n\\n will work\n"); + printf(" passing -x '\\n\\n' will not work\n"); printf(" -o given a query, outputs results to standard output\n"); exit(0); } @@ -704,6 +709,7 @@ int main(int argc, const char * argv[]) { const char* queryFontName = "Menlo"; const char* queryPromptString = ""; InitialQuery = [NSString stringWithUTF8String: ""]; + Separator = [NSString stringWithUTF8String: "\n"]; CGFloat queryFontSize = 26.0; SDNumRows = 10; SDReturnStringOnMismatch = NO; @@ -714,7 +720,7 @@ int main(int argc, const char * argv[]) { [NSApp setDelegate: delegate]; int ch; - while ((ch = getopt(argc, (char**)argv, "lvf:s:r:c:b:n:w:p:q:o:hium")) != -1) { + while ((ch = getopt(argc, (char**)argv, "lvf:s:r:c:b:n:w:p:q:x:o:hium")) != -1) { switch (ch) { case 'i': SDReturnsIndex = YES; break; case 'f': queryFontName = optarg; break; @@ -728,6 +734,7 @@ int main(int argc, const char * argv[]) { case 'm': SDReturnStringOnMismatch = YES; break; case 'p': queryPromptString = optarg; break; case 'q': InitialQuery = [NSString stringWithUTF8String: optarg]; break; + case 'x': Separator = [NSString stringWithUTF8String: optarg]; break; case 'o': queryStdout(delegate, optarg); break; case '?': case 'h': From 0c1aaa2a62aeabfbbfe274fb7f3a0967e2a7f097 Mon Sep 17 00:00:00 2001 From: 750 Date: Fri, 22 Nov 2024 01:29:32 +0300 Subject: [PATCH 2/4] #47 n2: visualise whitespace characters --- SDAppDelegate.m | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/SDAppDelegate.m b/SDAppDelegate.m index 962e281..f613b6a 100644 --- a/SDAppDelegate.m +++ b/SDAppDelegate.m @@ -18,6 +18,7 @@ static int SDPercentWidth; static BOOL SDUnderlineDisabled; static BOOL SDReturnStringOnMismatch; +static BOOL VisualizeWhitespaceCharacters; /******************************************************************************/ /* Boilerplate Subclasses */ @@ -75,7 +76,12 @@ - (id) initWithString:(NSString*)str { self.raw = str; self.normalized = [self.raw lowercaseString]; self.indexSet = [NSMutableIndexSet indexSet]; - self.displayString = [[NSMutableAttributedString alloc] initWithString:self.raw attributes:nil]; + + NSString* displayStringRaw = self.raw; + if (VisualizeWhitespaceCharacters) { + displayStringRaw = [[self.raw stringByReplacingOccurrencesOfString:@"\n" withString:@"⏎"] stringByReplacingOccurrencesOfString:@"\t" withString:@"⇥"]; + } + self.displayString = [[NSMutableAttributedString alloc] initWithString:displayStringRaw attributes:nil]; } return self; } @@ -684,6 +690,7 @@ static void usage(const char* name) { printf(" beware of escaping:\n"); printf(" passing -x \\n\\n will work\n"); printf(" passing -x '\\n\\n' will not work\n"); + printf(" -y show newline and tab as symbols (⏎ ⇥)\n"); printf(" -o given a query, outputs results to standard output\n"); exit(0); } @@ -702,6 +709,7 @@ int main(int argc, const char * argv[]) { @autoreleasepool { [NSApp setActivationPolicy: NSApplicationActivationPolicyAccessory]; + VisualizeWhitespaceCharacters = NO; SDReturnsIndex = NO; SDUnderlineDisabled = NO; const char* hexColor = HexFromSDColor(NSColor.systemBlueColor); @@ -720,7 +728,7 @@ int main(int argc, const char * argv[]) { [NSApp setDelegate: delegate]; int ch; - while ((ch = getopt(argc, (char**)argv, "lvf:s:r:c:b:n:w:p:q:x:o:hium")) != -1) { + while ((ch = getopt(argc, (char**)argv, "lvyf:s:r:c:b:n:w:p:q:x:o:hium")) != -1) { switch (ch) { case 'i': SDReturnsIndex = YES; break; case 'f': queryFontName = optarg; break; @@ -735,6 +743,7 @@ int main(int argc, const char * argv[]) { case 'p': queryPromptString = optarg; break; case 'q': InitialQuery = [NSString stringWithUTF8String: optarg]; break; case 'x': Separator = [NSString stringWithUTF8String: optarg]; break; + case 'y': VisualizeWhitespaceCharacters = YES; break; case 'o': queryStdout(delegate, optarg); break; case '?': case 'h': From 7d4278200c23916b670e54a9eb28bad4f5a7e26b Mon Sep 17 00:00:00 2001 From: 750 Date: Fri, 22 Nov 2024 01:39:11 +0300 Subject: [PATCH 3/4] #47 n3: allow empty input --- SDAppDelegate.m | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/SDAppDelegate.m b/SDAppDelegate.m index f613b6a..56d47ca 100644 --- a/SDAppDelegate.m +++ b/SDAppDelegate.m @@ -19,6 +19,7 @@ static BOOL SDUnderlineDisabled; static BOOL SDReturnStringOnMismatch; static BOOL VisualizeWhitespaceCharacters; +static BOOL AllowEmptyInput; /******************************************************************************/ /* Boilerplate Subclasses */ @@ -648,7 +649,7 @@ - (NSArray*) getInputItems { NSData* inputData = [stdinHandle readDataToEndOfFile]; NSString* inputStrings = [[[NSString alloc] initWithData:inputData encoding:NSUTF8StringEncoding] stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]]; - if ([inputStrings length] == 0) + if ([inputStrings length] == 0 && !AllowEmptyInput) return nil; return [inputStrings componentsSeparatedByString: Separator]; @@ -691,6 +692,7 @@ static void usage(const char* name) { printf(" passing -x \\n\\n will work\n"); printf(" passing -x '\\n\\n' will not work\n"); printf(" -y show newline and tab as symbols (⏎ ⇥)\n"); + printf(" -e allow empty input (choose will show up even if there are no items to select)\n"); printf(" -o given a query, outputs results to standard output\n"); exit(0); } @@ -710,6 +712,7 @@ int main(int argc, const char * argv[]) { [NSApp setActivationPolicy: NSApplicationActivationPolicyAccessory]; VisualizeWhitespaceCharacters = NO; + AllowEmptyInput = NO; SDReturnsIndex = NO; SDUnderlineDisabled = NO; const char* hexColor = HexFromSDColor(NSColor.systemBlueColor); @@ -728,7 +731,7 @@ int main(int argc, const char * argv[]) { [NSApp setDelegate: delegate]; int ch; - while ((ch = getopt(argc, (char**)argv, "lvyf:s:r:c:b:n:w:p:q:x:o:hium")) != -1) { + while ((ch = getopt(argc, (char**)argv, "lvyef:s:r:c:b:n:w:p:q:x:o:hium")) != -1) { switch (ch) { case 'i': SDReturnsIndex = YES; break; case 'f': queryFontName = optarg; break; @@ -744,6 +747,7 @@ int main(int argc, const char * argv[]) { case 'q': InitialQuery = [NSString stringWithUTF8String: optarg]; break; case 'x': Separator = [NSString stringWithUTF8String: optarg]; break; case 'y': VisualizeWhitespaceCharacters = YES; break; + case 'e': AllowEmptyInput = YES; break; case 'o': queryStdout(delegate, optarg); break; case '?': case 'h': From d23744eb5ea82bb40099348594ae94f344fede2a Mon Sep 17 00:00:00 2001 From: 750 <37119951+750@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:52:55 +0300 Subject: [PATCH 4/4] Update README.md Add snippet manager example --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index 6efc5c7..978ce85 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,17 @@ ls /Applications/ /Applications/Utilities/ /System/Applications/ /System/Applica xargs -I {} open -a "{}.app" ``` +### Use as a snippet manager + +Suppose you have some snippets in a text file and you want to quickly search and paste them with choose. Here is a command that you can bind to some shortcut with something like Karabiner: +```bash +cat snippets_separated_with_two_newline_symbols.txt | choose -e -m -x \n\n - | pbcopy - && osascript -e 'tell application "System Events" to keystroke "v" using command down' +``` + +This will prompt choose, get its output, copy it to pasteboard, and trigger a paste shortcut `command+v`. + +For this to work in Karabiner, you need to give it access via Privacy & Security -> Accessibility -> karabiner_console_user_server (typically located at `/Library/Application Support/org.pqrs/Karabiner-Elements/bin/karabiner_console_user_server`), otherwise you will get `System Events got an error: osascript is not allowed to send keystrokes. (1002)` + ## License See [MIT LICENSE](./LICENSE).