I'm attempting to create a syntax file for Python loaded from $VIM/after/syntax/python.vim that generates rules to highlight "else" based on context; python allows "else" to be used for "while" and "for" loops as well as in "try" blocks after "except" entries. I've gotten fairly close to achieving the behaviour I want, but I'm stuck now and have not been able to figure out how to resolve some remaining issues. I've attached the script to this email along with a sample Python file with some test cases. Note that being able to see a difference in the "else" coloring is contingent on the color scheme you're using having a different coloring for "Repeater" and "Conditional" tokens, so I've also included a screenshot of how things render on my system.
Eric -- -- You received this message from the "vim_use" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_use" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
" Author: Eric Pruitt " Description: Context-sensitive highlighting for `else` clauses. " These are blocks that need to be excluded from the LoopElse and TryElse " regions to avoid unnecessarily activating them. The current list allows this " script to work with the default Python syntax file included with Vim (at " least the one that comes with 7.3 and 7.4) as well as Dmitry Vasiliev's " [enhanced syntax file](http://www.vim.org/scripts/script.php?script_id=790). " If highlighting appears to be broken with another syntax file, determine the " by moving the cursor on top of the improperly highlighted word and executing " the following command: " " :echo synIDattr(synID(line("."), col("."), 1), "name") " " Add the displayed name to the list below, then restart Vim. let s:excludedRegions = [ \ "pythonDoctestValue", \ "pythonBytesContent", \ "pythonBytesError", \ "pythonDottedName", \ "pythonFunction", \] let s:indentLevels = range(15, 0, -1) let s:allMatchNames = \ join([""] + s:indentLevels, ",pythonLoopElse") . \ join([""] + s:indentLevels, ",pythonTryElse") let s:allbutList = join(s:excludedRegions, ",") "syn keyword pythonRepeat contained else "syn keyword None else for s:indentLevel in s:indentLevels " Remove current pythonLoopElse name from the list of excluded blocks. let s:invalidContexts = substitute(s:allMatchNames, ',pythonLoopElse' . s:indentLevel . '\>', '', '') execute printf( \ 'syn region pythonLoopBlock%i start="^\( \|\t\)\{%i\}\(for\|while\)" end="^\( \|\t\)\{,%i\}\S\+" transparent keepend contains=ALLBUT,%s%s', \ s:indentLevel, \ s:indentLevel, \ s:indentLevel, \ s:allbutList, \ s:invalidContexts) execute printf( \ 'syn match pythonLoopElse%i "^\( \|\t\)\{%i\}else\>" contained', \ s:indentLevel, \ s:indentLevel) execute printf('hi def link pythonLoopElse%i Repeat', s:indentLevel) endfor for s:indentLevel in s:indentLevels let s:invalidContexts = substitute(s:allMatchNames, ',pythonTryElse' . s:indentLevel . '\>', '', '') execute printf( \ 'syn region pythonTryBlock%i start="^\( \|\t\)\{%i\}\(except\)" end="^\( \|\t\)\{%i\}\S\+" transparent keepend contains=ALLBUT,%s%s', \ s:indentLevel, \ s:indentLevel, \ s:indentLevel, \ s:allbutList, \ s:invalidContexts) execute printf( \ 'syn match pythonTryElse%i "^\( \)\{%i\}else\>" contained', \ s:indentLevel, \ s:indentLevel) execute printf('hi def link pythonTryElse%i Exception', s:indentLevel) endfor
# "else" is never highlighted correctly when the loop blocks are not indented.
while False:
pass
else:
pass
if False:
# This works OK
while False:
pass
else:
pass
# The "else" is not highligted correctly
while False:
while False:
pass
else:
pass
# This (still) works OK
if False:
pass
else:
pass
class Highlight():
# The second function defintion loses its highlighting
def nothing():
while False:
while False:
pass
def function():
pass
<<attachment: rendered-test-cases.png>>
