I've just noticed, after years using Vim, that the two double quote characters opening and closing a string in a bash script have different colors, which I can verify by simply writing var="var" in a shell script or opening up my ~/.bashrc.

This seems to be independent of the colorscheme, and I can also reproduce it without my .vimrc, by opening

vi -u NONE ~/.bashrc

and then entering in Vim the following

:syntax enable
:colo pablo

(Those two colors are really different with pablo: yellow the opening double quote, blue-ish the closing one.)

I think that the answer to my question should be in /usr/share/vim/vim82/syntax/sh.vim (which is sourced by the bash.vim in the same directory), but that file is a bit too complex for me to understand.

Here's a screencast asciicast

In case it's relevant, this is the output of vim --version:

VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Aug 29 2020 00:50:37)
Included patches: 1-1523
Compiled by Arch Linux
Huge version with GTK3 GUI.  Features included (+) or not (-):
+acl               -farsi             +mouse_sgr         +tag_binary
+arabic            +file_in_path      -mouse_sysmouse    -tag_old_static
+autocmd           +find_in_path      +mouse_urxvt       -tag_any_white
+autochdir         +float             +mouse_xterm       +tcl/dyn
-autoservername    +folding           +multi_byte        +termguicolors
+balloon_eval      -footer            +multi_lang        +terminal
+balloon_eval_term +fork()            -mzscheme          +terminfo
+browse            +gettext           +netbeans_intg     +termresponse
++builtin_terms    -hangul_input      +num64             +textobjects
+byte_offset       +iconv             +packages          +textprop
+channel           +insert_expand     +path_extra        +timers
+cindent           +ipv6              +perl/dyn          +title
+clientserver      +job               +persistent_undo   +toolbar
+clipboard         +jumplist          +popupwin          +user_commands
+cmdline_compl     +keymap            +postscript        +vartabs
+cmdline_hist      +lambda            +printer           +vertsplit
+cmdline_info      +langmap           +profile           +virtualedit
+comments          +libcall           +python/dyn        +visual
+conceal           +linebreak         +python3/dyn       +visualextra
+cryptv            +lispindent        +quickfix          +viminfo
+cscope            +listcmds          +reltime           +vreplace
+cursorbind        +localmap          +rightleft         +wildignore
+cursorshape       +lua/dyn           +ruby/dyn          +wildmenu
+dialog_con_gui    +menu              +scrollbind        +windows
+diff              +mksession         +signs             +writebackup
+digraphs          +modify_fname      +smartindent       +X11
+dnd               +mouse             +sound             -xfontset
-ebcdic            +mouseshape        +spell             +xim
+emacs_tags        +mouse_dec         +startuptime       -xpm
+eval              +mouse_gpm         +statusline        +xsmp_interact
+ex_extra          -mouse_jsbterm     -sun_workshop      +xterm_clipboard
+extra_search      +mouse_netterm     +syntax            -xterm_save
   system vimrc file: "/etc/vimrc"
     user vimrc file: "$HOME/.vimrc"
 2nd user vimrc file: "~/.vim/vimrc"
      user exrc file: "$HOME/.exrc"
  system gvimrc file: "/etc/gvimrc"
    user gvimrc file: "$HOME/.gvimrc"
2nd user gvimrc file: "~/.vim/gvimrc"
       defaults file: "$VIMRUNTIME/defaults.vim"
    system menu file: "$VIMRUNTIME/menu.vim"
  fall-back for $VIM: "/usr/share/vim"
Compilation: gcc -c -I. -Iproto -DHAVE_CONFIG_H -DFEAT_GUI_GTK  -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/harfbuzz -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/fribidi -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/gio-unix-2.0 -I/usr/include/atk-1.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include -I/usr/include/at-spi-2.0 -pthread    -march=x86-64 -mtune=generic -O2 -pipe -fno-plt -D_REENTRANT  -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1       
Linking: gcc   -L. -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -fstack-protector-strong -rdynamic -Wl,-export-dynamic -Wl,-E -Wl,-rpath,/usr/lib/perl5/5.32/core_perl/CORE  -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -L/usr/local/lib -Wl,--as-needed -o vim   -lgtk-3 -lgdk-3 -lz -lpangocairo-1.0 -lpango-1.0 -lharfbuzz -latk-1.0 -lcairo-gobject -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0  -lSM -lICE -lXt -lX11 -lXdmcp -lSM -lICE  -lm -ltinfo -lelf    -lcanberra  -lacl -lattr -lgpm -ldl   -Wl,-E -Wl,-rpath,/usr/lib/perl5/5.32/core_perl/CORE -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -fstack-protector-strong -L/usr/local/lib  -L/usr/lib/perl5/5.32/core_perl/CORE -lperl -lpthread -ldl -lm -lcrypt -lutil -lc   -L/usr/lib -ltclstub8.6 -ldl -lz -lpthread -lm
  • 2
    Screenshot? I’ve never experienced that, and I write quite a bit of shell. – D. Ben Knoble Aug 29 '20 at 13:23
  • 1
    @D.BenKnoble, updated with a screencast :) – Enlico Aug 29 '20 at 13:55
  • I can reproduce that. Left quote is styled with shQuote while right one with shSpecial. The rule for a double quoted string (shDoubleQuote) sets nextgroup=shSpecialStart and I think this is what triggers that situation, but I can't tell whether this was intentional or not... – filbranden Aug 29 '20 at 14:53
  • This seems to have been introduced in version 190 of sh.vim. DrChip has a more recent version 193 on his website, maybe that fixes it? Otherwise, perhaps try a downgrade to 189? – filbranden Aug 29 '20 at 15:07
  • 1
    Yeah this bug was introduced in 190 and was later fixed in 193... I'll post an answer. – filbranden Aug 29 '20 at 15:14

This bug was introduced on the Vim runtime update of May 12, 2020, with the update of syntax/sh.vim from version 189 to version 190 from April 14, 2020, which updated the shDoubleQuoted rule to include the part in bold below:

syn region  shDoubleQuote   matchgroup=shQuote start=+"+ matchgroup=shSpecial skip=+\\"+ end=+"+     contained   contains=@shDblQuoteList,shStringSpecial,@Spell nextgroup=shSpecialStart

This seems to have been fixed on the latest version by DrChip, who is the maintainer of this syntax file. In version 193, the one currently available from his website, that line now also includes:

syn region  shDoubleQuote   matchgroup=shQuote start=+"+ matchgroup=shSpecial skip=+\\"+ matchgroup=shQuote end=+"+      contained   contains=@shDblQuoteList,shStringSpecial,@Spell nextgroup=shSpecialStart

You can upgrade your local installation to the latest version of Vim by downloading the sh.vim.gz file from DrChip's website, uncompressing it and saving it to ~/.vim/syntax/sh.vim on your local machine, at least until the upstream Vim runtime catches up with the update that contains the fix for this issue. (You might want to consider updating your runtimes directly, expecting that your next Vim upgrade might already include this change.)

Unfortunately, there doesn't seem to be a source repository or bug tracker where these changes can be tracked. But it seems to me that the intent of the initial change was to highlight a backslash-escaped sequence in a double quoted string using the shSpecial group, but in introducing this change it also affected the end match of the region (the closing double quote), which is what was then fixed with the second change, which resets the match group back to shQuote for the end pattern.


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.