Zsh bad substitution error in zshrc

zsh

I have this in my .zhsrc file:

[[ -n "${key[Home]}"    ]]  && bindkey  "${key[Home]}"    beginning-of-line     

Pressing Home on my keyboard does seem to trigger going to the beggining of line, so it seems to work, however whenever I edit the .zshrc in vim and save it SyntasticCheck zsh reports a "bad substitution" error.

Is this an error on my part or a bug in the syntax checker?

Edit in response to comment:

No I do not get an error when Zsh starts and yes Syntastic checker says the error is on that line.

$ sed -n /Home/l .zshrc
key[Home]=${terminfo[khome]}$
[[ -n "${key[Home]}"    ]]  && bindkey  "${key[Home]}"    beginning-o\
f-line$

EDIT 2. Output of zsh -vn .zshrc

I cleaned up my .zshrc file to this:

echo OK
[[ -n "${key[Home]}"    ]]  && bindkey  "${key[Home]}"    beginning-of-line
echo OK2

When I start my shell I see both OK and OK2, no errors show. But here's the output of zsh -vn .zshrc

# /etc/zsh/zshenv: system-wide .zshenv file for zsh(1).
#
# This file is sourced on all invocations of the shell.
# If the -f flag is present or if the NO_RCS option is
# set within this file, all other initialization files
# are skipped.
#
# This file should contain commands to set the command
# search path, plus other important environment variables.
# This file should not contain commands that produce
# output or assume the shell is attached to a tty.
#
# Global Order: zshenv, zprofile, zshrc, zlogin

if [[ -z "$PATH" || "$PATH" == "/bin:/usr/bin" ]]
then
        export PATH="/usr/local/bin:/usr/bin:/bin:/usr/games"
fi
echo OK
[[ -n "${key[Home]}"    ]]  && bindkey  "${key[Home]}"    beginning-of-line
.zshrc:2: bad substitution

Edit 3

Version: zsh 5.0.7 (x86_64-pc-linux-gnu)

Best Answer

That was a bug in some older versions of zsh fixed in 5.1. Changelog:

2015-07-15 Barton E. Schaefer

  • 35799: Src/params.c: with NO_EXEC, parse parameter subscript expressions to correctly balance enclosing braces, but do not perform the subscripting

after it was reported the same day.

With those versions, it can be reproduced with:

$ zsh -nc '${a[1]}'
zsh:1: bad substitution

According to git bisect, the bug was introduced in 2011 in a fix to a similar issue for associative arrays in commit dfc26195c916d54163a3f0dd2eb159db2d974569, starting with version zsh-4.3.12

More generally, zsh -n (or anyshell -n) is quite limited in its ability to lint code as since it's not running the code, it can't do much in areas where the way some code is evaluated depends on some code that was run beforehand.

For instance ${a[1+]} is invalid for an array, but OK for a hash. Without knowing which zsh -n just doesn't complain.

It can also give false positives like in:

alias aslongas=while
aslongas whatever; do
  something
done

Where it complains about that unexpected do because it has not acknowledged aslongas as an alias for while.

Related Question