mirror of https://github.com/python/cpython
Add a script that auto-generates a Vim syntax highlighting file for Python.
Just symlink or copy python.vim to ~/.vim/syntax/ . Also included is a sample Python file with basic expressions to make sure they are highlighted. Also add a Vim directory in Misc to hold all Vim configuration files.
This commit is contained in:
parent
d074beb692
commit
a4fe18227d
|
@ -0,0 +1,145 @@
|
|||
" Auto-generated Vim syntax file for Python
|
||||
"
|
||||
" To use: copy or symlink to ~/.vim/syntax/python.vim
|
||||
|
||||
|
||||
if exists("b:current_syntax")
|
||||
finish
|
||||
endif
|
||||
|
||||
if exists("python_highlight_all")
|
||||
let python_highlight_numbers = 1
|
||||
let python_highlight_builtins = 1
|
||||
let python_highlight_exceptions = 1
|
||||
let python_highlight_space_errors = 1
|
||||
endif
|
||||
|
||||
syn keyword pythonStatement assert break continue del except exec finally
|
||||
syn keyword pythonStatement global lambda pass print raise return try yield
|
||||
|
||||
syn keyword pythonStatement def class nextgroup=pythonFunction skipwhite
|
||||
|
||||
syn match pythonFunction "[a-zA-Z_][a-zA-Z0-9_]*" contained
|
||||
|
||||
syn keyword pythonRepeat for while
|
||||
|
||||
syn keyword pythonConditional if elif else
|
||||
|
||||
syn keyword pythonOperator and in is not or
|
||||
|
||||
syn keyword pythonPreCondit import from
|
||||
|
||||
syn match pythonComment "#.*$" contains=pythonTodo
|
||||
|
||||
syn keyword pythonTodo TODO FIXME XXX contained
|
||||
|
||||
syn region pythonString matchgroup=Normal start=+[uU]\='+ end=+'+ skip=+\\\\\|\\'+ contains=pythonEscape
|
||||
syn region pythonString matchgroup=Normal start=+[uU]\="+ end=+"+ skip=+\\\\\|\\"+ contains=pythonEscape
|
||||
syn region pythonString matchgroup=Normal start=+[uU]\="""+ end=+"""+ contains=pythonEscape
|
||||
syn region pythonString matchgroup=Normal start=+[uU]\='''+ end=+'''+ contains=pythonEscape
|
||||
syn region pythonString matchgroup=Normal start=+[uU]\=[rR]'+ end=+'+ skip=+\\\\\|\\'+
|
||||
syn region pythonString matchgroup=Normal start=+[uU]\=[rR]"+ end=+"+ skip=+\\\\\|\\"+
|
||||
syn region pythonString matchgroup=Normal start=+[uU]\=[rR]"""+ end=+"""+
|
||||
syn region pythonString matchgroup=Normal start=+[uU]\=[rR]'''+ end=+'''+
|
||||
|
||||
syn match pythonEscape +\\[abfnrtv\'"\\]+ contained
|
||||
syn match pythonEscape "\\\o\{1,3}" contained
|
||||
syn match pythonEscape "\\x\x\{2}" contained
|
||||
syn match pythonEscape "\(\\u\x\{4}\|\\U\x\{8}\)" contained
|
||||
|
||||
syn match pythonEscape "\\$"
|
||||
|
||||
|
||||
if exists("python_highlight_numbers")
|
||||
syn match pythonNumber "\<0x\x\+[Ll]\=\>"
|
||||
syn match pythonNumber "\<\d\+[LljJ]\=\>"
|
||||
syn match pythonNumber "\.\d\+\([eE][+-]\=\d\+\)\=[jJ]\=\>"
|
||||
syn match pythonNumber "\<\d\+\.\([eE][+-]\=\d\+\)\=[jJ]\=\>"
|
||||
syn match pythonNumber "\<\d\+\.\d\+\([eE][+-]\=\d\+\)\=[jJ]\=\>"
|
||||
|
||||
endif
|
||||
|
||||
|
||||
if exists("python_highlight_builtins")
|
||||
syn keyword pythonBuiltin unichr all set abs vars int __import__ unicode
|
||||
syn keyword pythonBuiltin enumerate reduce coerce intern exit issubclass
|
||||
syn keyword pythonBuiltin divmod file Ellipsis apply isinstance open any
|
||||
syn keyword pythonBuiltin locals help filter basestring slice copyright min
|
||||
syn keyword pythonBuiltin super sum tuple hex execfile long id xrange chr
|
||||
syn keyword pythonBuiltin complex bool zip pow dict True oct NotImplemented
|
||||
syn keyword pythonBuiltin map None float hash getattr buffer max reversed
|
||||
syn keyword pythonBuiltin object quit len repr callable credits setattr
|
||||
syn keyword pythonBuiltin eval frozenset sorted ord __debug__ hasattr
|
||||
syn keyword pythonBuiltin delattr False input license classmethod type
|
||||
syn keyword pythonBuiltin raw_input list iter compile reload range globals
|
||||
syn keyword pythonBuiltin staticmethod str property round dir cmp
|
||||
|
||||
endif
|
||||
|
||||
|
||||
if exists("python_highlight_exceptions")
|
||||
syn keyword pythonException GeneratorExit ImportError RuntimeError
|
||||
syn keyword pythonException UnicodeTranslateError MemoryError StopIteration
|
||||
syn keyword pythonException PendingDeprecationWarning EnvironmentError
|
||||
syn keyword pythonException LookupError OSError DeprecationWarning
|
||||
syn keyword pythonException UnicodeError FloatingPointError ReferenceError
|
||||
syn keyword pythonException NameError OverflowWarning IOError SyntaxError
|
||||
syn keyword pythonException FutureWarning SystemExit Exception EOFError
|
||||
syn keyword pythonException StandardError ValueError TabError KeyError
|
||||
syn keyword pythonException ZeroDivisionError SystemError
|
||||
syn keyword pythonException UnicodeDecodeError IndentationError
|
||||
syn keyword pythonException AssertionError TypeError IndexError
|
||||
syn keyword pythonException RuntimeWarning KeyboardInterrupt UserWarning
|
||||
syn keyword pythonException SyntaxWarning UnboundLocalError ArithmeticError
|
||||
syn keyword pythonException Warning NotImplementedError AttributeError
|
||||
syn keyword pythonException OverflowError UnicodeEncodeError
|
||||
|
||||
endif
|
||||
|
||||
|
||||
if exists("python_highlight_space_errors")
|
||||
syn match pythonSpaceError display excludenl "\S\s\+$"ms=s+1
|
||||
syn match pythonSpaceError display " \+\t"
|
||||
syn match pythonSpaceError display "\t\+ "
|
||||
|
||||
endif
|
||||
|
||||
|
||||
hi def link pythonStatement Statement
|
||||
hi def link pythonStatement Statement
|
||||
hi def link pythonFunction Function
|
||||
hi def link pythonRepeat Repeat
|
||||
hi def link pythonConditional Conditional
|
||||
hi def link pythonOperator Operator
|
||||
hi def link pythonPreCondit PreCondit
|
||||
hi def link pythonComment Comment
|
||||
hi def link pythonTodo Todo
|
||||
hi def link pythonString String
|
||||
hi def link pythonEscape Special
|
||||
hi def link pythonEscape Special
|
||||
|
||||
if exists("python_highlight_numbers")
|
||||
hi def link pythonNumber Number
|
||||
endif
|
||||
|
||||
if exists("python_highlight_builtins")
|
||||
hi def link pythonBuiltin Function
|
||||
endif
|
||||
|
||||
if exists("python_highlight_exceptions")
|
||||
hi def link pythonException Exception
|
||||
endif
|
||||
|
||||
if exists("python_highlight_space_errors")
|
||||
hi def link pythonSpaceError Error
|
||||
endif
|
||||
|
||||
|
||||
" Uncomment the 'minlines' statement line and comment out the 'maxlines'
|
||||
" statement line; changes behaviour to look at least 2000 lines previously for
|
||||
" syntax matches instead of at most 200 lines
|
||||
syn sync match pythonSync grouphere NONE "):$"
|
||||
syn sync maxlines=200
|
||||
"syn sync minlines=2000
|
||||
|
||||
let b:current_syntax = "python"
|
|
@ -0,0 +1,36 @@
|
|||
"""Test file for syntax highlighting of editors.
|
||||
|
||||
Meant to cover a wide range of different types of statements and expressions.
|
||||
Not necessarily sensical.
|
||||
|
||||
"""
|
||||
assert True
|
||||
def foo(): pass
|
||||
foo() # Uncoloured
|
||||
while False: pass
|
||||
1 and 2
|
||||
if False: pass
|
||||
from sys import path
|
||||
# Comment
|
||||
# XXX catch your attention
|
||||
'single-quote', u'unicode'
|
||||
"double-quote"
|
||||
"""triple double-quote"""
|
||||
'''triple single-quote'''
|
||||
r'raw'
|
||||
ur'unicode raw'
|
||||
'escape\n'
|
||||
'\04' # octal
|
||||
'\xFF' # hex
|
||||
'\u1111' # unicode character
|
||||
1
|
||||
1L
|
||||
1.0
|
||||
.1
|
||||
1+2j
|
||||
[] # Uncoloured
|
||||
{} # Uncoloured
|
||||
() # Uncoloured
|
||||
all
|
||||
GeneratorExit
|
||||
trailing_whitespace = path
|
|
@ -0,0 +1,232 @@
|
|||
import keyword
|
||||
import exceptions
|
||||
import __builtin__
|
||||
from string import Template
|
||||
|
||||
comment_header = """" Auto-generated Vim syntax file for Python
|
||||
"
|
||||
" To use: copy or symlink to ~/.vim/syntax/python.vim"""
|
||||
|
||||
statement_header = """
|
||||
if exists("b:current_syntax")
|
||||
finish
|
||||
endif"""
|
||||
|
||||
statement_footer = '''
|
||||
" Uncomment the 'minlines' statement line and comment out the 'maxlines'
|
||||
" statement line; changes behaviour to look at least 2000 lines previously for
|
||||
" syntax matches instead of at most 200 lines
|
||||
syn sync match pythonSync grouphere NONE "):$"
|
||||
syn sync maxlines=200
|
||||
"syn sync minlines=2000
|
||||
|
||||
let b:current_syntax = "python"'''
|
||||
|
||||
looping = ('for', 'while')
|
||||
conditionals = ('if', 'elif', 'else')
|
||||
boolean_ops = ('and', 'in', 'is', 'not', 'or')
|
||||
import_stmts = ('import', 'from')
|
||||
object_defs = ('def', 'class')
|
||||
|
||||
exception_names = frozenset(exc for exc in dir(exceptions)
|
||||
if not exc.startswith('__'))
|
||||
|
||||
# Need to include functions that start with '__' (e.g., __import__), but
|
||||
# nothing that comes with modules (e.g., __name__), so just exclude anything in
|
||||
# the 'exceptions' module since we want to ignore exceptions *and* what any
|
||||
# module would have
|
||||
builtin_names = frozenset(builtin for builtin in dir(__builtin__)
|
||||
if builtin not in dir(exceptions))
|
||||
|
||||
escapes = (r'+\\[abfnrtv\'"\\]+', r'"\\\o\{1,3}"', r'"\\x\x\{2}"',
|
||||
r'"\(\\u\x\{4}\|\\U\x\{8}\)"', r'"\\$"')
|
||||
|
||||
todos = ("TODO", "FIXME", "XXX")
|
||||
|
||||
# XXX codify?
|
||||
numbers = (r'"\<0x\x\+[Ll]\=\>"', r'"\<\d\+[LljJ]\=\>"',
|
||||
'"\.\d\+\([eE][+-]\=\d\+\)\=[jJ]\=\>"',
|
||||
'"\<\d\+\.\([eE][+-]\=\d\+\)\=[jJ]\=\>"',
|
||||
'"\<\d\+\.\d\+\([eE][+-]\=\d\+\)\=[jJ]\=\>"')
|
||||
|
||||
contained = lambda x: "%s contained" % x
|
||||
|
||||
def str_regexes():
|
||||
"""Generator to yield various combinations of strings regexes"""
|
||||
regex_template = Template('matchgroup=Normal ' +
|
||||
'start=+[uU]\=${raw}${sep}+ ' +
|
||||
'end=+${sep}+ ' +
|
||||
'${skip} ' +
|
||||
'${contains}')
|
||||
skip_regex = Template(r'skip=+\\\\\|\\${sep}+')
|
||||
for raw in ('', '[rR]'):
|
||||
for separator in ("'", '"', '"""', "'''"):
|
||||
if len(separator) == 1:
|
||||
skip = skip_regex.substitute(sep=separator)
|
||||
else:
|
||||
skip = ''
|
||||
if not raw:
|
||||
contains = 'contains=pythonEscape'
|
||||
else:
|
||||
contains = ''
|
||||
yield regex_template.substitute(raw=raw, sep=separator, skip=skip,
|
||||
contains = contains)
|
||||
|
||||
space_errors = (r'excludenl "\S\s\+$"ms=s+1', r'" \+\t"', r'"\t\+ "')
|
||||
|
||||
statements = (
|
||||
('',
|
||||
# XXX Might need to change pythonStatement since have
|
||||
# specific Repeat, Conditional, Operator, etc. for 'while',
|
||||
# etc.
|
||||
[("Statement", "pythonStatement", "keyword",
|
||||
(kw for kw in keyword.kwlist
|
||||
if kw not in (looping + conditionals + boolean_ops +
|
||||
import_stmts + object_defs))
|
||||
),
|
||||
("Statement", "pythonStatement", "keyword",
|
||||
(' '.join(object_defs) +
|
||||
' nextgroup=pythonFunction skipwhite')),
|
||||
("Function","pythonFunction", "match",
|
||||
contained('"[a-zA-Z_][a-zA-Z0-9_]*"')),
|
||||
("Repeat", "pythonRepeat", "keyword", looping),
|
||||
("Conditional", "pythonConditional", "keyword",
|
||||
conditionals),
|
||||
("Operator", "pythonOperator", "keyword", boolean_ops),
|
||||
("PreCondit", "pythonPreCondit", "keyword", import_stmts),
|
||||
("Comment", "pythonComment", "match",
|
||||
'"#.*$" contains=pythonTodo'),
|
||||
("Todo", "pythonTodo", "keyword",
|
||||
contained(' '.join(todos))),
|
||||
("String", "pythonString", "region", str_regexes()),
|
||||
("Special", "pythonEscape", "match",
|
||||
(contained(esc) for esc in escapes
|
||||
if not '$' in esc)),
|
||||
("Special", "pythonEscape", "match", r'"\\$"'),
|
||||
]
|
||||
),
|
||||
("python_highlight_numbers",
|
||||
[("Number", "pythonNumber", "match", numbers)]
|
||||
),
|
||||
("python_highlight_builtins",
|
||||
[("Function", "pythonBuiltin", "keyword", builtin_names)]
|
||||
),
|
||||
("python_highlight_exceptions",
|
||||
[("Exception", "pythonException", "keyword",
|
||||
exception_names)]
|
||||
),
|
||||
("python_highlight_space_errors",
|
||||
[("Error", "pythonSpaceError", "match",
|
||||
("display " + err for err in space_errors))]
|
||||
)
|
||||
)
|
||||
|
||||
def syn_prefix(type_, kind):
|
||||
return 'syn %s %s ' % (type_, kind)
|
||||
|
||||
def fill_stmt(iterable, fill_len):
|
||||
"""Yield a string that fills at most fill_len characters with strings
|
||||
returned by 'iterable' and separated by a space"""
|
||||
# Deal with trailing char to handle ' '.join() calculation
|
||||
fill_len += 1
|
||||
overflow = None
|
||||
it = iter(iterable)
|
||||
while True:
|
||||
buffer_ = []
|
||||
total_len = 0
|
||||
if overflow:
|
||||
buffer_.append(overflow)
|
||||
total_len += len(overflow) + 1
|
||||
overflow = None
|
||||
while total_len < fill_len:
|
||||
try:
|
||||
new_item = it.next()
|
||||
buffer_.append(new_item)
|
||||
total_len += len(new_item) + 1
|
||||
except StopIteration:
|
||||
if buffer_:
|
||||
break
|
||||
if not buffer_ and overflow:
|
||||
yield buffer_
|
||||
return
|
||||
else:
|
||||
return
|
||||
if total_len > fill_len:
|
||||
overflow = buffer_.pop()
|
||||
total_len -= len(overflow) - 1
|
||||
ret = ' '.join(buffer_)
|
||||
assert len(ret) <= fill_len
|
||||
yield ret
|
||||
|
||||
FILL = 80
|
||||
|
||||
def main(file_path):
|
||||
FILE = open(file_path, 'w')
|
||||
try:
|
||||
# Comment for file
|
||||
print>>FILE, comment_header
|
||||
print>>FILE, ''
|
||||
# Statements at start of file
|
||||
print>>FILE, statement_header
|
||||
print>>FILE, ''
|
||||
# Generate case for python_highlight_all
|
||||
print>>FILE, 'if exists("python_highlight_all")'
|
||||
for statement_var, statement_parts in statements:
|
||||
if statement_var:
|
||||
print>>FILE, ' let %s = 1' % statement_var
|
||||
else:
|
||||
print>>FILE, 'endif'
|
||||
print>>FILE, ''
|
||||
# Generate Python groups
|
||||
for statement_var, statement_parts in statements:
|
||||
if statement_var:
|
||||
print>>FILE, 'if exists("%s")' % statement_var
|
||||
indent = ' '
|
||||
else:
|
||||
indent = ''
|
||||
for colour_group, group, type_, arguments in statement_parts:
|
||||
if not isinstance(arguments, basestring):
|
||||
prefix = syn_prefix(type_, group)
|
||||
if type_ == 'keyword':
|
||||
stmt_iter = fill_stmt(arguments,
|
||||
FILL - len(prefix) - len(indent))
|
||||
try:
|
||||
while True:
|
||||
print>>FILE, indent + prefix + stmt_iter.next()
|
||||
except StopIteration:
|
||||
print>>FILE, ''
|
||||
else:
|
||||
for argument in arguments:
|
||||
print>>FILE, indent + prefix + argument
|
||||
else:
|
||||
print>>FILE, ''
|
||||
|
||||
else:
|
||||
print>>FILE, indent + syn_prefix(type_, group) + arguments
|
||||
print>>FILE, ''
|
||||
else:
|
||||
if statement_var:
|
||||
print>>FILE, 'endif'
|
||||
print>>FILE, ''
|
||||
print>>FILE, ''
|
||||
# Associating Python group with Vim colour group
|
||||
for statement_var, statement_parts in statements:
|
||||
if statement_var:
|
||||
print>>FILE, ' if exists("%s")' % statement_var
|
||||
indent = ' '
|
||||
else:
|
||||
indent = ' '
|
||||
for colour_group, group, type_, arguments in statement_parts:
|
||||
print>>FILE, (indent + "hi def link %s %s" %
|
||||
(group, colour_group))
|
||||
else:
|
||||
if statement_var:
|
||||
print>>FILE, ' endif'
|
||||
print>>FILE, ''
|
||||
# Statements at the end of the file
|
||||
print>>FILE, statement_footer
|
||||
finally:
|
||||
FILE.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main("python.vim")
|
Loading…
Reference in New Issue