junegunn / fzf.vim

fzf :heart: vim
MIT License
9.59k stars 582 forks source link

Alt- bindings broken in terminal buffer #1361

Closed ivanbrennan closed 2 years ago

ivanbrennan commented 2 years ago

I use alt-p and alt-n to navigate command history, so my FZF_DEFAULT_OPTS includes the following bindings:

--bind=alt-p:previous-history
--bind=alt-n:next-history

and I've configured my terminal and vim to recognize these keys:

exec "set <M-p>=\<Esc>p"
exec "set <M-n>=\<Esc>n"

It used to work, but after a recent upgrade, it stopped working as expected. Now, it works if I call,

fzf#run({'source': 'ls'})

but if I call,

call fzf#run({'source': 'ls', 'down': '50%'})

then rather than triggering history commands, the alt- bindings enter ð and î characters in the search string, respectively.

This is the commit that changed the behavior: 85ae7459103c3aeef39383d8c8a4fbbdb9fb5f64 It seems that the bindings don't work in a terminal buffer.

My previous (working) set up involved the following:

fzf:     0.25.0
fzf-vim: git revision 02a192ea0bed22a015e005b281e55e0da2a8e496
vim:     8.2.1522
bash:    4.4.23

The new (broken) set up involves the following:

fzf:     0.29.0
fzf-vim: git revision d6aa21476b2854694e6aa7b0941b8992a906c5ec
vim:     8.2.3877
bash:    5.1.12

Both systems are running linux, specifically NixOS.

Any advice about how to debug this would be greatly appreciated :)

ivanbrennan commented 2 years ago

I found the solution in :help terminal-special-keys.

Since the terminal emulator simulates an xterm, only escape sequences that both Vim and xterm recognize will be available in the terminal window. If you want to pass on other escape sequences to the job running in the terminal you need to set up forwarding.

Adding the following to my vim configuration did the trick:

tmap <expr> <M-n> SendToTerm("\<Esc>n")
tmap <expr> <M-p> SendToTerm("\<Esc>p")

func! SendToTerm(keys)
  call term_sendkeys('', a:keys)
  return ''
endf