mptre / pick

A fuzzy search tool for the command-line
MIT License
814 stars 42 forks source link

Silently pass through on single choice/match #296

Closed avivey closed 5 years ago

avivey commented 5 years ago

Hi, I have a feature suggestion:

If the input is only one option, pass it silently and don't go interactive.

My use case: I have a shortcut for git ls-files | grep $@ | xargs less, which basically finds a file by name and displays it. Obviously this is a little awkward if the grep matches multiple files, so I'd like to replace grep with pick, but only pop up a menu if there's actually more than one result to pick from.

I guess this can also make sense if -q is supplied and exactly one result is matched.

What do you think?

mptre commented 5 years ago

What do you think?

I think you already can achieve the behavior you're requesting with a shell script:

!/bin/sh

set -e

filter() { cat >"$TMP1"

if [ "$(wc -l "$TMP1" | awk '{print $1}')" -gt 1 ]; then
    env LINES=10 pick -X <"$TMP1"
else
    cat "$TMP1"
fi

}

TMP1="$(mktemp -t pick.XXXXXX)" trap "rm -f $TMP1" 0

git ls-files | grep -e "$1" | filter | xargs -r "${PAGER:-less}"

ghost commented 5 years ago
#!/bin/sh

filter ()
{
    FILTER="$( awk '
        BEGIN   { n = 0 }
        /'$1'/  { print $0; n++ }
        END { exit n }'
    )"

    [ $? -gt 1 ] && { echo "$FILTER" | pick; } || echo "$FILTER"
}

git ls-files | filter "$1" | xargs less
ghost commented 5 years ago
diff --git a/pick.c b/pick.c
index 9a3f422..354c98b 100644
--- a/pick.c
+++ b/pick.c
@@ -107,6 +107,7 @@ main(int argc, char *argv[])
        const struct choice     *choice;
        char                    *input;
        int                      c;
+       int                      one_choice = 0;
        int                      output_description = 0;
        int                      rc = 0;

@@ -115,8 +116,11 @@ main(int argc, char *argv[])
        if (pledge("stdio tty rpath wpath cpath", NULL) == -1)
                err(1, "pledge");

-       while ((c = getopt(argc, argv, "dhoq:KSvxX")) != -1)
+       while ((c = getopt(argc, argv, "1dhoq:KSvxX")) != -1)
                switch (c) {
+               case '1':
+                       one_choice = 1;
+                       break;
                case 'd':
                        descriptions = 1;
                        break;
@@ -165,13 +169,17 @@ main(int argc, char *argv[])
        }

        input = get_choices();
-       tty_init(1);
+       if (one_choice && choices.length == 1)
+               choice = &choices.v[0];
+       else {
+               tty_init(1);

-       if (pledge("stdio tty", NULL) == -1)
-               err(1, "pledge");
+               if (pledge("stdio tty", NULL) == -1)
+                       err(1, "pledge");

-       choice = selected_choice();
-       tty_restore(1);
+               choice = selected_choice();
+               tty_restore(1);
+       }
        if (choice != NULL) {
                printf("%s\n", choice->string);
                if (output_description)
@@ -190,11 +198,12 @@ main(int argc, char *argv[])
 __dead void
 usage(int status)
 {
-       fprintf(stderr, "usage: pick [-hvKS] [-d [-o]] [-x | -X] [-q query]\n"
+       fprintf(stderr, "usage: pick [-hvKS] [-1] [-d [-o]] [-x | -X] [-q query]\n"
            "    -h          output this help message and exit\n"
            "    -v          output the version and exit\n"
            "    -K          disable toggling of keypad transmit mode\n"
            "    -S          disable sorting\n"
+           "    -1          disable selection if there is only one choice\n"
            "    -d          read and display descriptions\n"
            "    -o          output description of selected on exit\n"
            "    -x          enable alternate screen\n"
git ls-files | grep "$1" | pick -1 | xargs less
mptre commented 5 years ago

Plenty of alternatives at this point, closing for now.