1

So I have a BASH script I'm modifying and I've been noticing large blocks of script with broken syntax highlighting. They appear as though I have an unpaired double quote somewhere, despite all quotes in and around the affected lines being properly paired and the script executing perfectly fine in that region. The broken highlighting spans multiple functions, and seems to be related to the escaped quote at the end of the eval local value=\"\${WORLD_$2[$1]}\" line. The issue occurs in multiple other places in this file, all issue instances seem

I've had this issue appear on both Debian 10 Vim 8.1 and on MacVim 8.2.539 on two different machines.

Here's where the issue first occurs in my code:

...
# Get the value of a world property
# $1: The world ID
# $2: The property name
world_property() {
    # Get the current value
    eval local value=\"\${WORLD_$2[$1]}\" 
    ### Issue begins after the final end quote of previous line #467

    ### ...
    ### multiple function closings and new function openings omitted
    ### ...

    error_exit NAME_NOT_FOUND "Could not find id for world \"$2\" for server \"${SERVER_NAME[$1]}\"." 
    ### Issue stops from end of previous line #614
}

(Triple hashed comments mine)

So, any ideas why these lines would cause the syntax highlighter to invert its interpretation of the opening and closing of quotes at these lines? Alternatively, is there some way I can change the two lines in question to maintain functionality and avoid the issue?

I've uploaded the entire script as a gist so you can see the issue for yourself and play with the file.

4
  • I think you should be able to use ' here, which should fix the issue and is arguably cleaner as well: eval 'local value="${WORLD_$2[$1]}"' Commented Jul 3, 2020 at 7:47
  • 1
    Welcome to Vi and Vim!
    – D. Ben Knoble
    Commented Jul 3, 2020 at 14:58
  • @MartinTournoij the only problem with your solution is that $1 and $2 won't be expanded in single quotes--unless eval then evaluates them too?
    – D. Ben Knoble
    Commented Jul 3, 2020 at 14:59
  • @D.BenKnoble Thanks for the warm welcome! Commented Jul 4, 2020 at 0:43

1 Answer 1

2

So I have a BASH script I'm modifying and I've been noticing large blocks of script with broken syntax highlighting. They appear as though I have an unpaired double quote somewhere, despite all quotes in and around the affected lines being properly paired and the script executing perfectly fine in that region.

Yes, it's a very common issue:

So, any ideas why these lines would cause the syntax highlighter to invert its interpretation of the opening and closing of quotes at these lines?

The sh syntax plugin relies on regular expressions; this may be a case where one/some of them fail(s) to properly recognize a specific shell construct.

The broken highlighting spans multiple functions, and seems to be related to the escaped quote at the end of the eval local value=\"\${WORLD_$2[$1]}\" line. Alternatively, is there some way I can change the two lines in question to maintain functionality and avoid the issue?

shellcheck gives 254 notes/warnings/errors for your script.

You can visit each of them like this:

vim --clean -S <(cat <<'EOF'
    let &mp = 'shellcheck -s bash -f gcc %:p:S'
    let &efm = '%f:%l:%c: %t%*[^:]: %m [SC%n]'
    sil make
    copen
    setl nowrap
    nno <buffer><nowait><silent> gx :<c-u>call <sid>gx_shellcheck()<cr>
    fu s:gx_shellcheck() abort
        let error_number = getline('.')->matchstr('.\{-}|.\{-}\zs\d\+\ze\s*|')
        wincmd p
        exe 'ShellCheckWiki'..error_number
        wincmd p
    endfu
    com -bar -complete=custom,s:shellcheck_complete -nargs=1 ShellCheckWiki call s:shellcheck_wiki(<q-args>)
    fu s:shellcheck_wiki(number) abort
        let url = 'https://github.com/koalaman/shellcheck/wiki/SC'..a:number
        let cmd = 'xdg-open '..shellescape(url)
        sil call system(cmd)
    endfu
    fu s:shellcheck_complete(_a, _l, _p) abort
        return getqflist()->map({_,v -> v.nr})->join("\n")
    endfu
EOF
) /path/to/your/script

This should populate the quickfix list with all the warnings, and display them in the quickfix window. Use :cnext, :cprevious, :cfirst, :clast, :cc 123... to jump from one to another.

Once the quickfix list is populated, run :clist 15,17 to list the warnings 15 to 17:

15 /tmp/sh.sh:467 col 23 warning 1083: This { is literal. Check expression (missing ;/\n?) or quote it.
16 /tmp/sh.sh:467 col 30 note 2086: Double quote to prevent globbing and word splitting.
17 /tmp/sh.sh:467 col 36 warning 1083: This } is literal. Check expression (missing ;/\n?) or quote it.

Those are relevant to your eval line. Run :cc 15 to jump to the 15th error. Focus the quickfix window, then press gx; Vim should open a wiki page explaining the issue in more details. Here it should be the page SC1083.

Read the explanation and try to fix your line accordingly. Do the same for the other errors. It will make your script more robust, and – in the process – may fix your syntax highlighting issue.


If that doesn't help, have a look at :h ft-sh-syntax.


As a last resort, contact the current maintainer of the syntax plugin.

But bear in mind that:

well perhaps one should realize, that shell language is really ugly and the syntax highlighting probably won't always always work and one can always create a piece of code that the syntax highlighting will stumble over. Best is to avoid that then.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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