junegunn / fzf

:cherry_blossom: A command-line fuzzy finder
https://junegunn.github.io/fzf/
MIT License
64.38k stars 2.38k forks source link

Using fzf as a kind of "selection menu" #70

Closed d630 closed 10 years ago

d630 commented 10 years ago

I would like to use fzf as a kind of "selection menu", in that way dmenu may be used. Therefore, it would be nice, if fzf had:

junegunn commented 10 years ago

a modifiable prompt

So fzf currently prints > as the prompt, you mean you want to change it to an arbitrary string? Would it be enough even if it can't be changed during the run?

an option to print the query respectively the literal string to stdout, when fzf has not matched anything

I can imagine something like --print-query option, which makes fzf always print the query as the first line of its output. What do you think?

d630 commented 10 years ago

It would be nice, if there were an option to pass some infomation into fzf (using the prompt or a status line). dmenu has the option -p:

-p prompt
              defines the prompt to be displayed to the  left  of  the
              input field.

I can imagine a situation, when I want to browse parts of my file system (the prompt would show me the current directory without using pwd every time). For example like this:

#!/usr/bin/env bash

__fzf_hier()
{
    declare \
            child= \
            parent=$1 \
            home_root=/home

    __menu_cmd() { sort -r | fzf -x -i +s ; }
    #__menu_cmd() { sort -r | fzf -x -i +s --prompt=${1:->} ; }
    #__menu_cmd() { sort | dmenu -p "${1:->}" -l 10 -b -f -i ; }

    child=$(find "$parent" -mindepth 1 -maxdepth 1 -type d \
                 -printf '%f\n' |
                 __menu_cmd "[${parent}]")
    parent=${parent}/${child}

    while [[ $child ]]
    do
        child=$({ printf '%s\n%s\n' "[.]" '[..]' ; find "${parent}" \
                -mindepth 1 -maxdepth 1 -printf '%f\n' ; } | \
                __menu_cmd "[${parent}]")
        case $child in
            \[..\])
                        [[ ${parent%/*} != $home_root ]] &&
                        parent=${parent%/*}
                        ;;
            \[.\])
                        parent=$parent
                        ;;
            *)          if [[ -f ${parent}/${child} ]]
                        then
                            : # xdg-open "$child"
                        else
                            parent=${parent}/${child}
                        fi
        esac
    done
}

__fzf_hier "$(pwd)"
d630 commented 10 years ago

An option to print the input field to stdout, when it is a non-matching query, would be nice. I can imagine a better urlview:

#!/usr/bin/env bash

# furlview.sh -- xterm,fzf,qupzilla,elinks 
# cli: $ furlview.sh
# gui: $ xterm -name "furlview-xterm" -e "furlview.sh;exit;bash"

declare -a urls=(https://github.com/junegunn/dotfiles
https://github.com/junegunn/goyo.vim
https://github.com/junegunn/redis-stat
https://github.com/junegunn/seoul256.vim
https://github.com/junegunn/vim-easy-align
)

__furlview()
{
    declare -a furls=$(printf '%s\n' $@ |
                grep -oP -e '((http|https|gopher|ftp|ftps|webdav|webdavs|dav|davs):(//)?[^ <>"\t]*|(www|ftp)[0-9]?\.[-a-z0-9.]+)[^ .,;\t\n\r<">\):]?[^, <>"\t]*[^ .,;\t\n\r<">\):]' |
                fzf -e -i -m)
    declare \
            time=0 \
            url=

    ((${#furls[@]} == 0 )) && exit 1

    if [[ $(xprop -id "$WINDOWID" WM_CLASS 2>/dev/null) =~ furlview-xterm ]]
    then
        for url in ${furls[@]}
        do
            (exec qupzilla "$url" &)
            ((time++))
        done
    elif tty 1>/dev/null 2>&1
    then
        (($(pgrep -cf furlview_elinks.sh) == 0)) &&
        (exec xterm -name "furlview-elinks" -e "furlview_elinks.sh ${furls[0]};exit;bash" 2>/dev/null &)
        for url in ${furls[@]}
        do
            (exec elinks -session-ring 1 -remote "openURL("$url", new-tab)" 2>/dev/null &)
            ((time++))
            sleep 1
        done
    else
        exit 1
    fi

    sleep "${time:-1}" && exit 0
}

__furlview "${urls[@]}"
#!/usr/bin/env bash

# furlview_elinks.sh

elinks -session-ring 1 ${1:+$1}

I would do then:

junegunn commented 10 years ago

These are really creative applications of fzf, thanks for sharing it. :+1:

An option to print the input field to stdout, when it is a non-matching query, would be nice.

As I mentioned in the previous comment, I'd prefer to have an option that prints the query regardless of whether the match was found or not for consistency.

# ...
query="${output[0]}"
matches=( ${output[@]:1} )

if [ ${#output[@]} -eq 0 ]; then
  # ...

What do you think?

junegunn commented 10 years ago

I've added --prompt and --print-query option to fzf and pushed to issue-70 branch. Could you try it and check if it can satisfy your needs?

d630 commented 10 years ago

Very very nice, and thank you a lot! Both options work fine for me.

For future releases I suggest a better tolerance of handling the input field and of its interaction with the selection line.

I have fit the scipts from above into right position and pushed them:

https://gist.github.com/D630/311f92b18b321b9833e0

https://gist.github.com/D630/1ee7225abe5ff69f44a3

Cheers!

junegunn commented 10 years ago

Great, I'll merge it into master.

For future releases I suggest a better tolerance of handling the input field and of its interaction with the selection line.

Could you be more specific? I'm interested in hearing about the problem you're having with fzf. Thanks.

d630 commented 10 years ago

I think about tab completion of the selection line in the input field.

junegunn commented 10 years ago

I see. I don't think the concept of tab completion goes nicely with fuzzy finder, but I'll think about it. Anyway the options are now merged to master and I'm closing this issue. Thanks.