junegunn / fzf

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

--bind command clears when capturing output in variable #1630

Open 0phoff opened 5 years ago

0phoff commented 5 years ago

Issue

If I want to capture the output of an fzf command (or pipe it to a next command), --bind commands that print things (using less) do not seem to work (I can only see the terminal flashing). It seems like it is launching less, but then exiting it for some reason

Example function

Here is an example of things going wrong. What I basically want to achieve is a git commit browser like you show on your wiki page, but it should also output the commit hash, so that I could use it in the following way: git commit --fixup=$(gcb)

gcb()
{
    local commit

    commit=$(git log --graph --date=relative --abbrev-commit --color=always --pretty=tformat:'%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%an %ad)%Creset' | \
        fzf --height=95% --ansi --no-sort --reverse --tiebreak=index \
        --bind=ctrl-s:toggle-sort \
        --bind "ctrl-g:execute:(echo {} | grep -o '[a-f0-9]\\{7\\}' | xargs -I % sh -c 'git show --color=always % 1>&2 | less -R')" \
        --bind "ctrl-f:execute:(echo {} | grep -o '[a-f0-9]\\{7\\}' | xargs -I % sh -c 'git show --color=always --name-status -r % 1>&2 | less -R')" \
    ) || return

    commit=${commit:2}
    echo ${commit%% *}
}

Note that inside the --bind commands, I needed to pipe the output from stdout to stderr (1>&2), because otherwise it would all be caught in the output commit variable.

iiey commented 5 years ago

Instead of 1>&2 I saw Junegunn once did in an example by redirect to /dev/tty. So something like this would work for you:

--bind "ctrl-g:execute:(git show --color=always $(grep -m1 -o '[a-f0-9]\{7,40\}' <<< {} | head -1 ) | less -R > /dev/tty)" \

Maybe someone could give a clue why output execute() of fzf inside $() or <() flickered and disappeared?

Note:

0phoff commented 5 years ago
  • better matching from at least 7 to 40 for SHA1 because 7 still ambiguous in big project
  • -m1 stop at first matching line and |head -1 so you don't get multiple results in case committer mentions about another commits in the first commit line

This seems nice, and I will probably use it. Thanks!

  • why not use --expect or --bind your git commit --fixup to a key, it's more convenient without much typing or getting error by abort

The reason for this, is so that the command can be used for more than just git commit --fixup. By having a command that returns a commit, you can use it for fixup, rebasing, ... Anything that takes a git commit hash can work with this log browser so this increases its potential.