With zsh multios set (setopt multios) it's possible to do things like:

< in1 < in2 > out


< in > out1 > out2

which is very convenient.

I want to combine this feature with brace expand (setopt braceexpand), so when I say:


(^I is a literal tab and invokes the completion system), I want it to expand to:

<in1 <in2 

but instead I get:

<in1 in2

Is there an easy way to modify this behavior?


Your desired behavior worked automatically with my existing completion settings (which were generated by plodding through compinstall a few times), so I took some time to narrow down the particular settings that were responsible.

The core functionality is provided by the _expand “completer”. You can include it like this:

zstyle ':completion:*' completer _expand

If you are also using the _completer completer, then _expand needs to be listed first. For example, here is my actual completer setting:

zstyle ':completion:*' completer _expand _complete _ignored _match _approximate _prefix

Next, to enable brace expansion, you need to have substitute enabled. This is enabled by default, but you can be explicit about it like this:

zstyle ':completion:*' substitute 1

If you do not want this enabled everywhere, you can disable it globally and enable it just for _expand like this:

zstyle ':completion:*' substitute 0
zstyle ':completion:*:expand:*' substitute 1

I tested this with zsh versions 4.3.11 and 5.0.2 by starting a fresh shell with zsh -df and sourcing a file containing the following:

zstyle ':completion:*' completer _expand
zstyle ':completion:*' substitute 0
zstyle ':completion:*:expand:*' substitute 1
autoload -Uz compinit

(The options multios and no_ingore_brace (which is what brace_expand is aliased to) are the defaults, so I did not have to explicitly change them.)

Then, I typed cat <in{1,2} and pressed Tab. You will need to press Tab several times: once for each expanded variant and one more time to get to the “all expansions” entry (a total of three times for the above example); I did not find a way to make this particular entry come first.

  • Turns out the problem was with my bindkey settings, but thank you for pushing me in the right direction, I'll award the bounty shortly. – Thor Feb 28 '13 at 8:32

This is the completer setting I'm using:

zstyle ':completion:*' completer _complete _list _expand _oldlist _ignored _match _correct _approximate _prefix

The substitute setting is the default, i.e. 1.

Seeing Chris's answer and pointers in the right direction, made me realize that this must have something to do with my configuration.

I started poking around with the completer order and the substitute setting, none of which changed the behavior. Comparing the settings, using the minimal configuration file provided by Chris, with my own, I narrowed the problem down to my bindkey file, and from there down to bindkey -v. This has the side-effect of setting ^I to expand-or-complete which for some reason botches desired expansion.

As I want to continue using the viins and vicmd keymaps the solution for me was to change tabs behavior to complete-word:

bindkey -M viins "\CI" complete-word
bindkey -M vicmd "\CI" complete-word


If you're using viins or viicmd as keymap remember to change ^I to complete-word:

bindkey -M viins "\CI" complete-word
bindkey -M vicmd "\CI" complete-word

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.