Place command output in shell for further editing

Viewed 474

I found a nice zsh command online that uses fzf to fuzzy-search shell history:

fh() {
  eval $( ([ -n "$ZSH_NAME" ] && fc -l 1 || history) | fzf +s --tac | sed 's/ *[0-9]* *//')
}

However, instead of eval-ing the command, I'd like to place it in my prompt and edit it further before running it, something like:

$ fh grep
(search happens)
$ grep -RI foo .  <--- cursor

I tried replacing eval with echo, which is better but doesn't give me the command to edit. Is there a way to do this in bash/zsh?

Here is a related thread with a suggestion to use xvkbd, but I was hoping there is something simpler.

2 Answers

In zsh, the vared builtin for the zsh line editor (ZLE) will let you edit an environment variable.
After editing, the updated variable can be used to execute the command:

fh() {
  fzfresult=$( ([ -n "$ZSH_NAME" ] && fc -l 1 || history) | fzf +s --tac | sed 's/ *[0-9]* *//')
  vared -p 'fzfout> ' -ac fzfresult
  ${fzfresult[@]}
}

In the vared command, -p sets the prompt. The -ac option changes the fzfresult variable to an array so we can execute it in the next step.

I don't have fzf installed, so this isn't completely tested, but the result should look like this:

% fh grep
fzfout> grep -RI foo .   <-- edit, hit enter, get output:
file1: text with foo
file4: more text with foobar

I ended up using this:

fh() {
   print -s $( ([ -n "$ZSH_NAME" ] && fc -l 1 || history) | fzf +s --tac | sed 's/ *[0-9]* *//')
}

ie silently print, followed by up-arrow, which brings up the command for editing. Would love to hear if there is a simpler way.

Related