[Python-checkins] r42569 - python/trunk/Misc/Vim python/trunk/Misc/Vim/python.vim python/trunk/Misc/Vim/syntax_test.py python/trunk/Misc/Vim/vim_syntax.py

brett.cannon python-checkins at python.org
Sat Feb 25 15:52:55 CET 2006


Author: brett.cannon
Date: Sat Feb 25 15:52:53 2006
New Revision: 42569

Added:
   python/trunk/Misc/Vim/
   python/trunk/Misc/Vim/python.vim   (contents, props changed)
   python/trunk/Misc/Vim/syntax_test.py   (contents, props changed)
   python/trunk/Misc/Vim/vim_syntax.py   (contents, props changed)
Log:
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.


Added: python/trunk/Misc/Vim/python.vim
==============================================================================
--- (empty file)
+++ python/trunk/Misc/Vim/python.vim	Sat Feb 25 15:52:53 2006
@@ -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"

Added: python/trunk/Misc/Vim/syntax_test.py
==============================================================================
--- (empty file)
+++ python/trunk/Misc/Vim/syntax_test.py	Sat Feb 25 15:52:53 2006
@@ -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 

Added: python/trunk/Misc/Vim/vim_syntax.py
==============================================================================
--- (empty file)
+++ python/trunk/Misc/Vim/vim_syntax.py	Sat Feb 25 15:52:53 2006
@@ -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")


More information about the Python-checkins mailing list