2

I recently switched from bash to zsh. One difference is that when typing a command in bash and I do Esc-* (in vi editing mode), bash will expand the glob inline immediately. For example, if I type:

$ ls
bar foo1 foo2 foo3
$ cp foo<Esc>*

bash will change the command to:

$ cp foo1 foo2 foo3

and position the cursor at the end of the line and put me back in insert mode. How can I get zsh to do the same thing?

1
1

In the default configuration, you get this effect from expand-word which is bound to ^X * (Ctrl+X *) in Emacs mode (if you want it in Vi mode, you'll have to bind it to a key). Unlike ESC * in bash, ^X * in zsh also expands variable and command substitutions.

Additionally, in the default configuration, pressing Tab after a word containing wildcards expands it to the list of matches.

If you have the option glob_complete on, then Tab cycles through the matches rather than inserting all of them. In this case, you can assign a key to the _all_matches completer (mentioned by Stéphane Chazelas in a comment). Quoting the example code in the manual:

setopt glob_complete
zle -C all-matches complete-word _generic
bindkey '^Xa' all-matches
zstyle ':completion:all-matches::::' completer _all_matches _complete
zstyle ':completion:all-matches:*' insert true

The difference between the completion widgets (default Tab and this all-matches) and the built-in widget expand-word is that expand-word does shell filename expansion, no matter what the completion context is, whereas Tab and all-matches use the completion context to determine how to process wildcards. For example, after rmdir *, ^X* expands to all files whereas ^Xa expands to directories only.

4
  • Since I want <Esc>* not ^X*, I did bindkey '\e*' all-matches. Everything else is the same. However, it doesn't work. Zsh just beeps. I've also found this link similar to (but not exactly the same as) yours. It doesn't work either. blog.iany.me/2013/04/select-multiple-zsh-completions-item – Paul J. Lucas Jun 8 '20 at 16:02
  • @PaulJ.Lucas Indeed it works with my configuration, but not in the default configuration. Apparently what makes it work in my configuration is setopt glob_complete, without which a simple Tab does what you want. I'd forgotten that the glob_complete effect was not the default. – Gilles 'SO- stop being evil' Jun 8 '20 at 16:15
  • Adding setopt glob_complete changes nothing. Tab also does nothing. FYI, my current set of zsh options starts here: github.com/paul-j-lucas/env/blob/master/dotfiles/bashrc#L18 – Paul J. Lucas Jun 8 '20 at 16:22
  • @PaulJ.Lucas Oh, you aren't using the “new-style completion” (compinit). Still, even without it, Tab inserts all matches for wildcards by default. Your configuration file is too long and complex for me to debug, but if echo *<TAB> doesn't replace the * by the list of files in the current directory, it must be due to something in there. – Gilles 'SO- stop being evil' Jun 8 '20 at 16:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.