5

I'm trying to switch from bash to zsh, but there is one main thing that I find inconvenient with zsh. I have unset the menucomplete option, bound tab to expand-or-complete-prefix, and bound alt-s to menu-complete.

However, once I invoke menu-complete by pressing alt-s, subsequently hitting tab continues to cycle through the menu-complete entries instead of exiting menu-complete and performing completion on the last displayed entry like in bash. Main reason why I want this is so I can quickly "go into" the last displayed directory in the case that I want to cd/ls into multiple nested directories.

I'm using zsh version 5.8 and have the following in my ~/.zshrc:

setopt autolist
unsetopt automenu autoremoveslash listambiguous menucomplete
bindkey '^i' expand-or-complete-prefix # Bind tab
bindkey '^[s' menu-complete # Bind alt-s to menu-complete

Here is a working example:

$ mkdir dir dir/a dir/b dir/b/d dir/c
$ ls dir/ <alt-s>
$ ls dir/a/ <alt-s>
$ ls dir/b/ <tab>
$ ls dir/c/ <tab>
$ ls dir/a/ <tab>
$ ls dir/b/ <tab>
$ ls dir/c/
...etc.

Instead, I want tab to "go into" dir/b/ like in bash:

$ ls dir/ <alt-s>
$ ls dir/a/ <alt-s>
$ ls dir/b/ <tab>
$ ls dir/b/d/  <-- Pressing tab exits menu-complete and immediately goes into the currently displayed directory.

Does anyone know how I can obtain this behavior? Thanks so much for your help!


Edit:

I found a somewhat mitigating solution with menuselect in zsh/complist by adding the following to ~/.zshrc:

zmodload -i zsh/complist
bindkey -M menuselect '^i' accept-line
zstyle ':completion:*' menu select=1

Now, pressing tab during a menu-complete operation exits menu-complete. However, it doesn't "go into" the last displayed directory and I have to press tab again to do autocomplete within that last displayed directory. So two tab presses in zsh instead of one in bash for the same functionality.

Note there is a different menuselect option:

bindkey -M menuselect '^i' accept-and-infer-next-history

which "goes into" the last displayed directory with one press of tab, but performs menu-select in that directory instead of just normal tab completion like what I want.

If anyone knows how I can get this functionality down to just one press of the tab key, would be much appreciated. Would it be possible to write a custom zle command for menuselect, for example, an accept-and-complete-next-history?

2 Answers 2

2

It takes quite a few lines of code to configure Zsh's completion system to do what you are asking here, even though it is in fact capable of it. Instead of doing it yourself, I would recommend using my zsh-autocomplete plugin instead. It gives you the following:

  1. Type anything and completions are automatically listed.
    • No need to press ⇥ Tab.
    • Type more to narrow down the choices.
    • This supports fuzzy, type-ahead completion, meaning you can type any part of the word you're looking for, as long as what you type next is further to the right in the target word.
  2. Press ⇥ Tab to insert the top completion.
    • If this is a directory, sub-directories are automatically listed.
    • Rinse, lather and repeat.
  3. If you cannot get the completion you want at the top, then you can use ↓ Down (plus the other arrow keys) to navigate to it.
    • If you're not seeing the completion you want at all, try pressing ⌃ Ctrl␣ Space. This will cause additional completion to be revealed, if available.
1

Hmm, your zsh-autocomplete plugin looks interesting Mr. Marlon, will have to check it out.

In any case, I figured out a solution to my original issue. Basically, I just created a simple widget to do what I wanted. In ~/.zshrc:

zmodload -i zsh/complist
accept-and-complete-next-history() {
    zle expand-or-complete-prefix
}
zle -N accept-and-complete-next-history
bindkey -M menuselect '^i' accept-and-complete-next-history
zstyle ':completion:*' menu select=1

Or equivalently:

zmodload -i zsh/complist
bindkey -M menuselect '^i' .expand-or-complete-prefix
zstyle ':completion:*' menu select=1
3
  • I'd really like to see a proper explanation of what this does and how. Nov 6, 2022 at 11:24
  • zmodload loads the completion listing extensions: zsh.sourceforge.io/Doc/Release/Zsh-Modules.html
    – Alan
    Nov 7, 2022 at 20:29
  • (Sorry forgot to finish that comment.) To be honest, I have since forgotten most of the details because once I got it working how I liked it, I just stuck with it. "Set and forget." Here are some hints, hopefully they help a bit: Putting '.' in front of the widget expand-or-complete-prefix uses the builtin widget even if it has been redefined: zsh.sourceforge.io/Guide/zshguide04.html select=1 because In the form ‘select=num’, menu selection will only be started if there are at least num matches: zsh.sourceforge.io/Doc/Release/Completion-System.html
    – Alan
    Nov 7, 2022 at 20:37

You must log in to answer this question.

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