1
  • I have some bindkey commands in my .zshrc file which behave as desired.
  • I start tmux; the same .zshrc is run, including the bindkeys but they don't function.
  • But then if I manually type them on the command prompt inside tmux, they do work again.

I've tried with an empty tmux.conf (tmux -L test -f /dev/null) so I know it's not my tmux conf.

  • zsh 5.8.1 (x86_64-ubuntu-linux-gnu)
  • tmux 3.2a
  • Gnome shell (has default TERM=xterm-256color)

It's like tmux is somehow resetting the bind keys after running my .zshrc?

After some testing, I found out that if I remove this line from my .zshrc, the problem goes away:

export EDITOR=`which vim`

Why?

3
  • Impossible to answer without seeing your .zshrc (please reduce it to a small file that reproduces the problem) and knowing which key(s) are problematic. Also post the difference in the output of bindkey inside and outside tmux, if there's any difference. May 22 at 9:26
  • @Gilles'SO-stopbeingevil' thanks, I tried to reproduce with small-enough-to-share-configs but can't. I bisected my .zshrc (which is massive) and found a quirk around EDITOR env var, see my answer below. May 22 at 11:33
  • Ah, yes, I forgot to ask: do you use vi-style key bindings in zsh? From your answer, you don't, except in tmux... May 22 at 11:49

2 Answers 2

1

Like several other popular shells, zsh offers two command line editing modes: Emacs-like (modeless) and Vi-like (with insert and command modes). Unlike other popular shells, zsh starts up in Vi-like mode if the environment variable VISUAL or EDITOR contains vi when zsh starts up.

You're setting the environment variable EDITOR in your .zshrc. When you open a terminal and the terminal emulator program starts zsh, EDITOR is not set, so zsh starts in Emacs mode. When you start a tmux session from inside that shell, EDITOR is set to a string containing vi in the environment of tmux, and so it's already set when zsh starts in a tmux window. So, inside tmux windows, zsh runs in Vi-like mode.

In Vi-like operating mode, there are two editing modes: insert and command. Each has its own key bindings, and bindkey with no option only applies to insert mode. So your custom bindings don't work in command mode, i.e. after pressing Escape. Most default bindings don't work either.

To avoid this, since you don't appear to want Vi-like mode, explicitly select Emacs-like mode by putting the following command before any other call to bindkey in your .zshrc:

bindkey -e

The real problem is that you're setting EDITOR in the wrong place. Generally speaking, don't set environment variables in shell initialization files (.bashrc, .zshrc), because they only take effect in programs that run from that shell. A program started directly from a GUI launcher won't inherit those variables, and so won't call your preferred editor. Instead, set environment variables in a file that is read when your login session starts, such as ~/.profile (for classical Unix-like sessions, including most X11-based setups).

1
  • Excellent, thanks for explaining that very clearly! I confirm that bindkey -e works, and good tip re ~/.profile and env vars (though possibly I'd need a .zprofile too, from what I've read - anyway!) Thanks. May 23 at 14:44
0

OK, I think this is going to turn out to be a local issue but here's what I've found out:

  • My .zshrc contains the line
    export EDITOR=`which vim`
    
  • That command results in a filepath to an excutable Neovim AppImage.
  • with EDITOR set to this file, things don't work.
  • removing the export didn't affect things
  • coding it so that var is only set if not in tmux did not help either.

I'm feeling like there's no point me trying to figure out if this is a bug or in what (tmux? zsh? the autocomplete thing I use? gnome-terminal? neovim? something deep and kernel about app images?)...

But just in case anyone else is affected, as well as the details in the question, I'm using

https://github.com/marlonrichert/zsh-autocomplete/

and the bindkeys that aren't working (there may be others; not sure)

bindkey '\t' menu-select "$terminfo[kcbt]" menu-select
bindkey -M menuselect '\t' menu-complete "$terminfo[kcbt]" reverse-menu-complete

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .