Commits

Tamas Kovacs  committed 317c988

Version 0.8.6

Handle cl:in-package, common-lisp:in-package (thanks to Philipp Marek), added option g:swank_host to allow connecting to remote Swank server, autodetection of Cake for Clojure (thanks to Chris Cahoon), set paredit mode also for .cl and .rkt files, recognise domain reversed package names in form com.gigamonkeys.pathnames (thanks to has2k1), added curly braces rainbow parenthesis for Clojure, added paredit handling of curly braces for Clojure, use SlimvIndent also for Clojure, handle line number returned in :compilation-result, bugfixes: removed double newline in :read-string (text input), when editing with cw in paredit mode, keep ending whitespaces (thanks to Mats Rauhala), compilation error when Swank does not return file name, skip dot character when Swank returns a dotted pair (a . b).

  • Participants
  • Parent commits 38ed29c

Comments (0)

Files changed (10)

 
 Slimv supports SLIME's debugger, profiler, cross reference, arglist, indentation, symbol name completion functions. The script also has a Common Lisp Hyperspec lookup feature and it is able to lookup symbols in the Clojure API, as well as in JavaDoc.
 
-Slimv comes with Paredit Mode, which is similar to the functionality of paredit.el in Emacs. Paredit Mode tries to maintain the balanced state of matched characters (parenthesis marks, square brackets, double quotes). Matched characters are inserted and removed in pairs, also when working with a block of text (well, mostly). Slimv also implements many paredit.el s-expression handling functions, like Split/Join/Wrap/Splice. Slurpage and Barfage known from Emacs is also possible but in a different fashion: you don't move the list element in or out of the list, rather you move the opening or closing parenthesis over the element or sub-list.
+Slimv comes with Paredit Mode, which is similar to the functionality of paredit.el in Emacs. Paredit Mode tries to maintain the balanced state of matched characters (parenthesis marks, square and curly braces, double quotes). Matched characters are inserted and removed in pairs, also when working with a block of text (well, mostly). Slimv also implements many paredit.el s-expression handling functions, like Split/Join/Wrap/Splice. Slurpage and Barfage known from Emacs is also possible but in a different fashion: you don't move the list element in or out of the list, rather you move the opening or closing parenthesis over the element or sub-list.
 
 Please visit the Slimv Tutorial for a more complete introduction:
 http://kovisoft.bitbucket.org/tutorial.html

File doc/paredit.txt

-*paredit.txt*                    Slimv               Last Change: 09 May 2011
+*paredit.txt*                    Slimv               Last Change: 25 Aug 2011
 
 Paredit mode for Slimv                                *paredit* *slimv-paredit*
-                               Version 0.8.3
+                               Version 0.8.6
 
 The paredit.vim plugin performs structured editing of s-expressions used in
 the Lisp or Clojure programming language.
 PAREDIT MODE                                                     *paredit-mode*
 
 Paredit mode is a special editing mode that keeps all matched characters
-(parentheses, square brackets, double quotes) balanced, i.e. all opening
+(parentheses, square and curly braces, double quotes) balanced, i.e. all opening
 characters have a matching closing character. Most text entering and erasing
 commands try to maintain the balanced state, so no single matched character is
 added or deleted, they are entered or removed in pairs.
 The function takes care of strings and comments, so no parenthesis and square
 bracket balancing is performed inside a string or comment.
+Please note that [] and {} pairs are not balanced for Lisp filetypes, only
+for Clojure.
 
 The idea is taken from the paredit mode of Emacs, but not all paredit.el
 editing functions are implemented or behave exactly the same way as they do
 or deleting till the end of the line, etc, then the deletion logic of a single
 character is iterated. This means that the whole line or the characters till
 the end of the line, etc are not necessarily deleted all. Depending on the
-number of open/close parentheses, square brackets, double quotes some of them
-might be kept in order to maintain the balanced state.
+number of open/close parentheses, square or curly braces, double quotes some
+of them might be kept in order to maintain the balanced state.
 For example if you press D in Normal mode to delete till the end of line
 between the a and b parameters of the following Clojure function definition:
 
 then it will stop at the matched closing parenthesis.
 
 
-Paredit mode is set by default for .lisp and .clj files, but it is possible
-to switch it out by putting the following statement in the .vimrc file:
+Paredit mode is set by default for .lisp, .cl, .clj, .scm and .rkt files, but
+it is possible to switch it out by putting the following statement in the
+.vimrc file:
 
     let g:paredit_mode = 0
 
     let g:slimv_loaded = 1
 
 Slimv core will not be loaded but paredit will be loaded and assigned to
-.lisp and .clj files.
+.lisp, .clj, .scm, etc files.
 
 
 Here follows a list of paredit keybindings:
                    top level form is reached.
                    Inserts ']' when inside comment or string.
 
+    {              Inserts '{}' and moves the cursor inside. Also adds leading
+                   or trailing spaces when needed.
+                   Inserts '{' when inside comment or string.
+
+    }              Moves the cursor to the next closing curly brace of the
+                   current list. When pressed again then moves to the next
+                   outer closing curly brace, etc, until the closing of the
+                   top level form is reached.
+                   Inserts '}' when inside comment or string.
+
     "              When outside of string, inserts '""' and moves the cursor
                    inside. When inside string then moves to the closing '"'.                   
                    Inserts '"' when inside comment. Also insert '"' when inside
                    For example pressing <Leader>w[ at position marked with |:
                        (aaa b|bb ccc)    --->    (aaa [bbb] ccc)
 
+    <Leader>w{     Wrap the current symbol in a pair of curly braces,
+                   similarly to <Leader>W.
+                   For example pressing <Leader>w{ at position marked with |:
+                       (aaa b|bb ccc)    --->    (aaa {bbb} ccc)
+
     <Leader>w"     Wrap the current symbol in a pair of double quotes,
                    similarly to <Leader>W.
                    For example pressing <Leader>w" at position marked with |:
     <Leader>w[     Wrap the current visual selection in a pair of square
                    brackets. The visual selection is kept.
 
+    <Leader>w{     Wrap the current visual selection in a pair of curly braces.
+                   The visual selection is kept.
+
     <Leader>w"     Wrap the current visual selection in a pair of double
                    quotes. The visual selection is kept.
 

File doc/slimv.txt

-*slimv.txt*                    Slimv                 Last Change: 19 Jul 2011
+*slimv.txt*                    Slimv                 Last Change: 25 Aug 2011
 
 Slimv                                                                  *slimv*
-                               Version 0.8.5
+                               Version 0.8.6
 
 The Superior Lisp Interaction Mode for Vim.
 This plugin is aimed to help Lisp development by interfacing between Vim and
          :echo g:slimv_lisp
          :echo g:slimv_client         
 
+- Q: The Slimv plugin is not loaded for a .lisp (or .clj, etc) file.
+- A: Filetype plugins should be enabled, check it via the :filetype command.
+     If needed, put this in your .vimrc file:
+         filetype plugin on
+         filetype indent on
+     You can check the scripts loaded with the :scriptnames command,
+     filetype.vim and ftplugin.vim should be listed in order to load other
+     filetype plugins.
+     The source buffer filetype should be lisp (or clojure, etc), check it via
+         :set ft?
+     The Slimv files should be in Vim's runtime path, check the path via
+         :set rtp?
+     slimv.vim should be in the ftplugin directory in the runtimepath,
+     there should be an ftplugin/lisp subdirectory containing slimv-lisp.vim.
+     Also make sure that no other ftplugin/lisp.vim is loaded that prevents
+     loading of the Slimv scripts.
+
 - Q: Why is SLIME functionality XYZ missing from Slimv?
 - A: There are two possible reasons:
      1. The dataflow of Slimv is one-directional: from client to server.
 ===============================================================================
 CHANGE LOG                                                    *slimv-changelog*
 
+0.8.6  - Handle cl:in-package, common-lisp:in-package (thanks to Philipp Marek).
+       - Added option g:swank_host to allow connecting to remote Swank server.
+       - Autodetection of Cake for Clojure (thanks to Chris Cahoon).
+       - Set Paredit mode also for .cl and .rkt files.
+       - Recognise domain reversed package names in form com.gigamonkeys.pathnames
+         (thanks to has2k1).
+       - Added curly braces rainbow parenthesis for Clojure.
+       - Added paredit handling of curly braces for Clojure.
+       - Use SlimvIndent also for Clojure.
+       - Handle line number returned in :compilation-result.
+       - Bugfix: removed double newline in :read-string (text input).
+       - Bugfix: when editing with cw in paredit mode, keep ending whitespaces
+         (thanks to Mats Rauhala).
+       - Bugfix: compilation error when Swank does not return file name.
+       - Bugfix: skip dot character when Swank returns a dotted pair (a . b).
+
 0.8.5  - Switch on indent plugins.
        - Do not complete empty string on <Tab>.
        - Added Clojure keywords to syntax plugin.
 Also thanks to Vlad Hanciuta, Marcin Fatyga, Dmitry Petukhov,
 Daniel Solano G�mez, Brian Kropf, Len Weincier, Andreas Salwasser,
 Jon Thacker, Andrew Hills, Jerome Baum, John Obbele, Andreas Fredriksson,
-�mer Sinan Agacan, Tobias Pflug for additional notes and contributions.
+�mer Sinan Agacan, Tobias Pflug, Chris Cahoon, Mats Rauhala for additional
+notes and contributions.
+
+I would also like to say a big thank you to everyone donating to support
+development. This is a one-element list at the moment: :)
+thanks to Paul Michael Bauer.
 
 Last but not least many thanks to my wife Andrea (for the Italians out there:
 hey, this is a female name in Hungary :) for her support and patience.

File doc/swank.txt

-*swank.txt*                    Slimv                 Last Change: 18 Jul 2011
+*swank.txt*                    Slimv                 Last Change: 13 Aug 2011
 
 SWANK client for Slimv                                    *swank* *slimv-swank*
-                               Version 0.8.5
+                               Version 0.8.6
 
 The Superior Lisp Interaction Mode for Vim.
 Slimv contains a SWANK client that can communicate with a running SWANK server
   part of SLIME) and Swank Clojure. If you intend to use your own version of
   SLIME, then you need to have your own SWANK server installed.
   For example Clojure users might consider installing Leiningen and run the
-  SWANK server via 'lein swank'.
+  SWANK server via 'lein swank', or use Cake via 'cake swank'.
 
 
 ===============================================================================
     let g:slimv_swank_cmd = '! xterm -e sbcl --load /usr/share/common-lisp/source/slime/start-swank.lisp &'
     let g:slimv_swank_clojure = '! xterm -e lein swank &'
 
+  On OS X the following or similar command may be used (but sometimes the above
+  Linux xterm command also works):
+
+    let g:slimv_swank_cmd = '!osascript -e "tell application \"Terminal\" to do script \"sbcl --load ~/.vim/slime/start-swank.lisp\""'
+    let g:slimv_swank_clojure = '!osascript -e "tell application \"Terminal\" to do script \"cake swank\""'
+
+  These are examples only, the Lisp command and the path to the SWANK server
+  may need to be changed in the command depending on the actual configuration.
+
   It is also possible to run the SWANK server manually prior running Vim.
   Slimv detects if a SWANK server is running and connects to it at the first
   evaluation request.
                      :dont-close t)
 
 
+                                                                 *g:swank_host*
+  Host name or IP address of the SWANK server. Default value is 'localhost'.
+  The SWANK server may run on a remote machine, but currently only unencryplted
+  plain socket communication is supported, no SSH or whatsoever.
+  Please note that if the SWANK server is on a remote machine then Slimv is
+  unable to start it, so you need to run the SWANK server manually.
+
                                                                  *g:swank_port*
   The SWANK server is connected to port 4005 by default. This can be changed
   using the g:swank_port option.

File ftplugin/clojure/slimv-clojure.vim

 " slimv-clojure.vim:
 "               Clojure filetype plugin for Slimv
-" Version:      0.8.5
-" Last Change:  13 Jul 2011
+" Version:      0.8.6
+" Last Change:  05 Aug 2011
 " Maintainer:   Tamas Kovacs <kovisoft at gmail dot com>
 " License:      This file is placed in the public domain.
 "               No warranty, express or implied.
     if executable( 'lein' )
         return ['"lein repl"', 'clojure']
     endif
+    if executable( 'cake' )
+        return ['"cake repl"', 'clojure']
+    endif
     if executable( 'clojure' )
         return ['clojure', 'clojure']
     endif

File ftplugin/slimv.vim

 " slimv.vim:    The Superior Lisp Interaction Mode for VIM
-" Version:      0.8.5
-" Last Change:  02 Aug 2011
+" Version:      0.8.6
+" Last Change:  25 Aug 2011
 " Maintainer:   Tamas Kovacs <kovisoft at gmail dot com>
 " License:      This file is placed in the public domain.
 "               No warranty, express or implied.
 
     let cmd = ''
     if SlimvGetFiletype() == 'clojure'
-        " First autodetect 'lein swank'
+        " First autodetect Leiningen and Cake
         if executable( 'lein' )
             let cmd = '"lein swank"'
+        elseif executable( 'cake' )
+            let cmd = '"cake swank"'
         else
             " Check if swank-clojure is bundled with Slimv
             let swanks = split( globpath( &runtimepath, 'swank-clojure/swank/swank.clj'), '\n' )
     let g:slimv_swank = 1
 endif
 
+" Host name or IP address of the SWANK server
+if !exists( 'g:swank_host' )
+    let g:swank_host = 'localhost'
+endif
+
 " TCP port number to use for the SWANK server
 if !exists( 'g:swank_port' )
     let g:swank_port = 4005
     call SlimvRefreshReplBuffer()
 endfunction
 
-" Select symbol under cursor and return it
-function! SlimvSelectSymbol()
+" Set 'iskeyword' option depending on file type
+function! s:SetKeyword()
     if SlimvGetFiletype() == 'clojure'
-        setlocal iskeyword+=~,#,&,\|,{,},!,?
+        setlocal iskeyword+=~,#,&,\|,!,?
     else
         setlocal iskeyword+=~,#,&,\|,{,},[,],!,?
     endif
+endfunction
+
+" Select symbol under cursor and return it
+function! SlimvSelectSymbol()
+    call s:SetKeyword()
     let symbol = expand('<cword>')
     return symbol
 endfunction
 function! SlimvSelectSymbolExt()
     let save_iskeyword = &iskeyword
     if SlimvGetFiletype() == 'clojure'
-        setlocal iskeyword+=~,#,&,\|,{,},!,?,'
+        setlocal iskeyword+=~,#,&,\|,!,?,'
     else
         setlocal iskeyword+=~,#,&,\|,{,},[,],!,?,'
     endif
     if sel == ''
         call SlimvError( "Form is empty." )
         return 0
-    elseif sel == '(' || sel == '['
+    elseif sel == '(' || sel == '[' || sel == '{'
         call SlimvError( "Form is unbalanced." )
         return 0
     else
     if found
         if g:slimv_swank
             silent normal! ww
-            let s:swank_package = expand('<cword>')
+            let l:packagename_tokens = split(expand('<cWORD>'),')\|\s')
+            if l:packagename_tokens != []
+                let s:swank_package = l:packagename_tokens[0]
+            else
+                let s:swank_package = ''
+            endif
         else
             " Put the form just found at the beginning of the selection
             let sel = SlimvGetSelection()
     if SlimvGetFiletype() == 'clojure'
         call SlimvFindAddSel( 'in-ns' )
     else
-        call SlimvFindAddSel( 'in-package' )
+        call SlimvFindAddSel( '\(cl:\|common-lisp:\|\)in-package' )
     endif
 endfunction
 
     if !s:swank_connected
         let s:swank_version = ''
         let s:lisp_version = ''
-        python swank_connect( "g:swank_port", "result" )
-        if result != ''
+        if g:swank_host == ''
+            let g:swank_host = input( 'Swank server host name: ', 'localhost' )
+        endif
+        execute 'python swank_connect("' . g:swank_host . '", ' . g:swank_port . ', "result" )'
+        if result != '' && ( g:swank_host == 'localhost' || g:swank_host == '127.0.0.1' )
             " SWANK server is not running, start server if possible
             let swank = SlimvSwankCommand()
             if swank != ''
                 let starttime = localtime()
                 while result != '' && localtime()-starttime < g:slimv_timeout
                     sleep 500m
-                    python swank_connect( "g:swank_port", "result" )
+                    execute 'python swank_connect("' . g:swank_host . '", ' . g:swank_port . ', "result" )'
                 endwhile
                 redraw!
             endif
             " We are outside of strings and comments, now we shall count parens
             if form[i] == '('
                 let end = ')' . end
-            elseif form[i] == '['
+            elseif form[i] == '[' && SlimvGetFiletype() == 'clojure'
                 let end = ']' . end
-            elseif form[i] == ')' || form[i] == ']'
+            elseif form[i] == '{' && SlimvGetFiletype() == 'clojure'
+                let end = '}' . end
+            elseif form[i] == ')' || ((form[i] == ']' || form[i] == '}') && SlimvGetFiletype() == 'clojure')
                 if len( end ) == 0 || end[0] != form[i]
                     " Oops, too many closing parens or invalid closing paren
                     return 'ERROR'
     let l = line('.')
     let c = col('.') - 1
     let line = getline('.')
-    if SlimvGetFiletype() == 'clojure'
-        setlocal iskeyword+=~,#,&,\|,{,},!,?
-    else
-        setlocal iskeyword+=~,#,&,\|,{,},[,],!,?
-    endif
+    call s:SetKeyword()
     if s:swank_connected && c > 1 && line[c-2] =~ '\k'
         let save_ve = &virtualedit
         set virtualedit=onemore
 function! SlimvOmniComplete( findstart, base )
     if a:findstart
         " Locate the start of the symbol name
-        if SlimvGetFiletype() == 'clojure'
-            setlocal iskeyword+=~,#,&,\|,{,},!,?
-        else
-            setlocal iskeyword+=~,#,&,\|,{,},[,],!,?
-        endif
+        call s:SetKeyword()
         let upto = strpart( getline( '.' ), 0, col( '.' ) - 1)
         let p = match(upto, '\k\+$')
         return p 
 " Complete function for user-defined commands
 function! SlimvCommandComplete( arglead, cmdline, cursorpos )
     " Locate the start of the symbol name
-    if SlimvGetFiletype() == 'clojure'
-        setlocal iskeyword+=~,#,&,\|,{,},!,?
-    else
-        setlocal iskeyword+=~,#,&,\|,{,},[,],!,?
-    endif
+    call s:SetKeyword()
     let upto = strpart( a:cmdline, 0, a:cursorpos )
     let base = matchstr(upto, '\k\+$')
     let ext  = matchstr(upto, '\S*\k\+$')

File ftplugin/swank.py

 #
 # SWANK client for Slimv
 # swank.py:     SWANK client code for slimv.vim plugin
-# Version:      0.8.5
-# Last Change:  02 Aug 2011
+# Version:      0.8.6
+# Last Change:  22 Aug 2011
 # Maintainer:   Tamas Kovacs <kovisoft at gmail dot com>
 # License:      This file is placed in the public domain.
 #               No warranty, express or implied.
                 # Skip coment
                 pos = pos + parse_comment( sexpr[pos:] ) - 1
             elif not sexpr[pos] in string.whitespace + '\\':
-                # Parse keyword
+                # Parse keyword but ignore dot in dotted notation (a . b)
                 klen = parse_keyword( sexpr[pos:] )
-                result = result + [sexpr[pos:pos+klen]]
-                pos = pos + klen - 1
+                if klen > 1 or sexpr[pos] != '.':
+                    result = result + [sexpr[pos:pos+klen]]
+                    pos = pos + klen - 1
         pos = pos + 1
 
     if quote_cnt != 0:
     buf = ''
     warnings = struct[1]
     time = struct[3]
-    filename = struct[5]
+    filename = ''
+    if len(struct) > 5:
+        filename = struct[5]
+    if filename == '' or filename[0] != '"':
+        filename = '"' + filename + '"'
+    vim.command('let s:compiled_file=' + filename + '')
     vim.command("let qflist = []")
     if type(warnings) == list:
         buf = '\n' + str(len(warnings)) + ' compiler notes:\n\n'
                     buf = buf + snippet + '\n'
                 buf = buf + fname + ':' + pos + '\n'
                 buf = buf + '  ' + severity + ': ' + msg + '\n\n' 
-                [lnum, cnum] = parse_location(fname, int(pos))
+                if location[2][0] == ':line':
+                    lnum = pos
+                    cnum = 1
+                else:
+                    [lnum, cnum] = parse_location(fname, int(pos))
                 qfentry = "{'filename':'"+fname+"','lnum':'"+str(lnum)+"','col':'"+str(cnum)+"','text':'"+msg+"'}"
                 logprint(qfentry)
                 vim.command("call add(qflist, " + qfentry + ")")
 
                 elif message == ':indentation-update':
                     for el in r[1]:
-                        indent_info[ unquote(el[0]) ] = el[2]
+                        indent_info[ unquote(el[0]) ] = el[1]
 
                 elif message == ':new-package':
                     package = unquote( r[1] )
                             elif element == ':title':
                                 retval = retval + new_line(retval) + swank_parse_inspect(params)
                             elif element == ':compilation-result':
-                                filename = params[5]
-                                if filename[0] != '"':
-                                    filename = '"' + filename + '"'
-                                vim.command('let s:compiled_file=' + filename + '')
                                 retval = retval + new_line(retval) + swank_parse_compile(params) + prompt + '> '
                             else:
                                 if action.name == ':simple-completions':
 # Generic SWANK connection handling
 ###############################################################################
 
-def swank_connect(portvar, resultvar):
+def swank_connect(host, port, resultvar):
     """
     Create socket to swank server and request connection info
     """
 
     if not sock:
         try:
-            input_port = int(vim.eval(portvar))
-            swank_server = ('localhost', input_port)
+            input_port = port
+            swank_server = (host, input_port)
             sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
             sock.connect(swank_server)
             swank_connection_info()
             sock = None
             return sock
     vim.command('let ' + resultvar + '=""')
-    return sock
 
 def swank_disconnect():
     """
     form = vim.eval(formvar)
     if read_string:
         # We are in :read-string mode, pass string entered to REPL
-        swank_return_string('"' + form + '\n"')
+        swank_return_string('"' + form + '"')
     elif debug_activated and form[0] != '(' and form[0] != ' ':
         # We are in debug mode and an SLDB command follows (that is not an s-expr)
         if form[0] == '#':

File indent/clojure.vim

 " clojure.vim:
 "               Clojure indent plugin for Slimv
-" Version:      0.5.4
-" Last Change:  15 Nov 2009
+" Version:      0.8.6
+" Last Change:  13 Aug 2011
 " Maintainer:   Tamas Kovacs <kovisoft at gmail dot com>
 " License:      This file is placed in the public domain.
 "               No warranty, express or implied.
 
 runtime indent/**/lisp.vim
 
-set lisp
+setlocal nolisp
+setlocal autoindent
+setlocal indentexpr=SlimvIndent(v:lnum)
 

File plugin/paredit.vim

 " paredit.vim:
 "               Paredit mode for Slimv
-" Version:      0.8.5
-" Last Change:  29 Jun 2011
+" Version:      0.8.6
+" Last Change:  20 Aug 2011
 " Maintainer:   Tamas Kovacs <kovisoft at gmail dot com>
 " License:      This file is placed in the public domain.
 "               No warranty, express or implied.
 let s:skip_c  = 'synIDattr(synID(line("."), col("."), 0), "name") =~ "[Cc]omment"'
 let s:skip_sc = 'synIDattr(synID(line("."), col("."), 0), "name") =~ "[Ss]tring\\|[Cc]omment\\|[Ss]pecial"'
 
-" Regular expressions to identify special characters combinations used by paredit
-"TODO: add curly brace
-let s:any_matched_char   = '(\|)\|\[\|\]\|\"'
-let s:any_matched_pair   = '()\|\[\]\|\"\"'
-let s:any_opening_char   = '(\|\['
-let s:any_closing_char   = ')\|\]'
-let s:any_openclose_char = '(\|\[\|)\|\]'
-let s:any_wsopen_char    = '\s\|(\|\['
-let s:any_wsclose_char   = '\s\|)\|\]'
+" Valid macro prefix characters
 let s:any_macro_prefix   = "'" . '\|`\|#\|@\|\~\|,'
 
 " Repeat count for some remapped edit functions (like 'd')
 function! PareditInitBuffer()
     " Make sure to include special characters in 'iskeyword'
     " in case they are accidentally removed
+    " Also define regular expressions to identify special characters used by paredit
     if &ft == 'clojure'
-        setlocal iskeyword+=~,#,&,\|,{,},!,?
+        setlocal iskeyword+=~,#,&,\|,!,?
+        let b:any_matched_char   = '(\|)\|\[\|\]\|{\|}\|\"'
+        let b:any_matched_pair   = '()\|\[\]\|{}\|\"\"'
+        let b:any_opening_char   = '(\|\[\|{'
+        let b:any_closing_char   = ')\|\]\|}'
+        let b:any_openclose_char = '(\|)\|\[\|\]\|{\|}'
+        let b:any_wsopen_char    = '\s\|(\|\[\|{'
+        let b:any_wsclose_char   = '\s\|)\|\]\|}'
     else
         setlocal iskeyword+=~,#,&,\|,{,},[,],!,?
+        let b:any_matched_char   = '(\|)\|\"'
+        let b:any_matched_pair   = '()\|\"\"'
+        let b:any_opening_char   = '('
+        let b:any_closing_char   = ')'
+        let b:any_openclose_char = '(\|)'
+        let b:any_wsopen_char    = '\s\|('
+        let b:any_wsclose_char   = '\s\|)'
     endif
 
     if g:paredit_mode
         " Paredit mode is on: add buffer specific keybindings
         inoremap <buffer> <expr>   (            PareditInsertOpening('(',')')
         inoremap <buffer> <expr>   )            PareditInsertClosing('(',')')
-        inoremap <buffer> <expr>   [            PareditInsertOpening('[',']')
-        inoremap <buffer> <expr>   ]            PareditInsertClosing('[',']')
         inoremap <buffer> <expr>   "            PareditInsertQuotes()
         inoremap <buffer> <expr>   <BS>         PareditBackspace(0)
         inoremap <buffer> <expr>   <Del>        PareditDel()
         nnoremap <buffer> <silent> P            :<C-U>call PareditPut('P')<CR>
         execute 'nnoremap <buffer> <silent> ' . g:paredit_leader.'w(  :<C-U>call PareditWrap("(",")")<CR>'
         execute 'vnoremap <buffer> <silent> ' . g:paredit_leader.'w(  :<C-U>call PareditWrapSelection("(",")")<CR>'
-        execute 'nnoremap <buffer> <silent> ' . g:paredit_leader.'w[  :<C-U>call PareditWrap("[","]")<CR>'
-        execute 'vnoremap <buffer> <silent> ' . g:paredit_leader.'w[  :<C-U>call PareditWrapSelection("[","]")<CR>'
         execute 'nnoremap <buffer> <silent> ' . g:paredit_leader.'w"  :<C-U>call PareditWrap('."'".'"'."','".'"'."')<CR>"
         execute 'vnoremap <buffer> <silent> ' . g:paredit_leader.'w"  :<C-U>call PareditWrapSelection('."'".'"'."','".'"'."')<CR>"
+        if &ft == 'clojure'
+            inoremap <buffer> <expr>   [            PareditInsertOpening('[',']')
+            inoremap <buffer> <expr>   ]            PareditInsertClosing('[',']')
+            inoremap <buffer> <expr>   {            PareditInsertOpening('{','}')
+            inoremap <buffer> <expr>   }            PareditInsertClosing('{','}')
+            execute 'nnoremap <buffer> <silent> ' . g:paredit_leader.'w[  :<C-U>call PareditWrap("[","]")<CR>'
+            execute 'vnoremap <buffer> <silent> ' . g:paredit_leader.'w[  :<C-U>call PareditWrapSelection("[","]")<CR>'
+            execute 'nnoremap <buffer> <silent> ' . g:paredit_leader.'w{  :<C-U>call PareditWrap("{","}")<CR>'
+            execute 'vnoremap <buffer> <silent> ' . g:paredit_leader.'w{  :<C-U>call PareditWrapSelection("{","}")<CR>'
+        endif
 
         if g:paredit_shortmaps
             " Shorter keymaps: old functionality of KEY is remapped to <Leader>KEY
         " Paredit mode is off: remove keybindings
         silent! iunmap <buffer> (
         silent! iunmap <buffer> )
-        silent! iunmap <buffer> [
-        silent! iunmap <buffer> ]
         silent! iunmap <buffer> "
         silent! iunmap <buffer> <BS>
         silent! iunmap <buffer> <Del>
         silent! unmap  <buffer> c
         silent! unmap  <buffer> dd
         silent! unmap  <buffer> cc
+        if &ft == 'clojure'
+            silent! iunmap <buffer> [
+            silent! iunmap <buffer> ]
+            silent! iunmap <buffer> {
+            silent! iunmap <buffer> }
+        endif
     endif
 endfunction
 
         let putreg = getreg( '"' )
 
         " Find and keep unbalanced matched characters in the region
+        let endingwhitespace = matchstr(putreg, "\\s*$")
         let matched = s:GetMatchedChars( putreg, s:InsideString( "'<" ), s:InsideComment( "'<" ) )
         let matched = s:Unbalanced( matched )
         let matched = substitute( matched, '\s', '', 'g' )
+        if a:func == 'c'
+            let matched = matched . endingwhitespace
+        endif
 
         if matched == ''
             silent exe "normal! gvx"
         else
             silent exe "normal! gvc" . matched
             silent exe "normal! l"
+            if a:func == 'c'
+                silent exe "normal! " . string(len(endingwhitespace)) . "h"
+            endif
         endif
     endif
 
         " Number of opening and closing parens differ
         return 0
     endif
-    let b1 = searchpair( '\[', '', '\]', 'brnmW', s:skip_sc, matchb )
-    if b1 == 0
-        " Outside of all bracket-pairs
-        return 1
-    endif
-    let b2 = searchpair( '\[', '', '\]',  'rnmW', s:skip_sc, matchf )
-    if !(b1 == b2) && !(b1 == b2 - 1 && line[c-1] == '[') && !(b1 == b2 + 1 && line[c-1] == ']')
-        " Number of opening and closing brackets differ
-        return 0
+
+    if &ft == 'clojure'
+        let b1 = searchpair( '\[', '', '\]', 'brnmW', s:skip_sc, matchb )
+        let b2 = searchpair( '\[', '', '\]',  'rnmW', s:skip_sc, matchf )
+        if !(b1 == b2) && !(b1 == b2 - 1 && line[c-1] == '[') && !(b1 == b2 + 1 && line[c-1] == ']')
+            " Number of opening and closing brackets differ
+            return 0
+        endif
+        let b1 = searchpair( '{', '', '}', 'brnmW', s:skip_sc, matchb )
+        let b2 = searchpair( '{', '', '}',  'rnmW', s:skip_sc, matchf )
+        if !(b1 == b2) && !(b1 == b2 - 1 && line[c-1] == '{') && !(b1 == b2 + 1 && line[c-1] == '}')
+            " Number of opening and closing curly braces differ
+            return 0
+        endif
     endif
     return 1
 endfunction
             if a:lines[i] == ';'
                 let inside_comment = 1
             endif
-            if a:lines[i] == '(' || a:lines[i] == '[' || a:lines[i] == ')' || a:lines[i] == ']'
+            if a:lines[i] =~ b:any_openclose_char
                 let matched = strpart( matched, 0, i ) . a:lines[i] . strpart( matched, i+1 )
             endif
         endif
     while 1
         let matched = tmp
         let tmp = substitute( tmp, '(\(\s*\))',   ' \1 ', 'g')
-        let tmp = substitute( tmp, '\[\(\s*\)\]', ' \1 ', 'g')
+        if &ft == 'clojure'
+            let tmp = substitute( tmp, '\[\(\s*\)\]', ' \1 ', 'g')
+            let tmp = substitute( tmp, '{\(\s*\)}',   ' \1 ', 'g')
+        endif
         let tmp = substitute( tmp, '"\(\s*\)"',   ' \1 ', 'g')
         if tmp == matched
             " All paired chars eliminated
             let tmp = substitute( tmp, ')\(\s*\)(',   ' \1 ', 'g')
-            let tmp = substitute( tmp, '\]\(\s*\)\[', ' \1 ', 'g')
+            if &ft == 'clojure'
+                let tmp = substitute( tmp, '\]\(\s*\)\[', ' \1 ', 'g')
+                let tmp = substitute( tmp, '}\(\s*\){',   ' \1 ', 'g')
+            endif
             if tmp == matched
                 " Also no more inverse pairs can be eliminated
                 break
     if pos > 0 && line[pos-1] == '\' && (pos < 2 || line[pos-2] != '\')
         " About to enter a \( or \[
         return a:open
-    elseif line[pos] !~ s:any_wsclose_char && pos < len( line )
+    elseif line[pos] !~ b:any_wsclose_char && pos < len( line )
         " Add a space after if needed
         let retval = a:open . a:close . " \<Left>\<Left>"
     else
         let retval = a:open . a:close . "\<Left>"
     endif
-    if pos > 0 && line[pos-1] !~ s:any_wsopen_char && line[pos-1] !~ s:any_macro_prefix
+    if pos > 0 && line[pos-1] !~ b:any_wsopen_char && line[pos-1] !~ s:any_macro_prefix
         " Add a space before if needed
         let retval = " " . retval
     endif
     if pos == 0
         " We are at the beginning of the line
         return "\<BS>"
-    elseif s:InsideString() && line[pos-1] =~ s:any_openclose_char
+    elseif s:InsideString() && line[pos-1] =~ b:any_openclose_char
         " Deleting a paren inside a string
         return "\<BS>"
-    elseif pos > 1 && line[pos-1] =~ s:any_matched_char && line[pos-2] == '\' && (pos < 3 || line[pos-3] != '\')
+    elseif pos > 1 && line[pos-1] =~ b:any_matched_char && line[pos-2] == '\' && (pos < 3 || line[pos-3] != '\')
         " Deleting an escaped matched character
         return "\<BS>\<BS>"
-    elseif line[pos-1] !~ s:any_matched_char
+    elseif line[pos-1] !~ b:any_matched_char
         " Deleting a non-special character
         return "\<BS>"
     elseif line[pos-1] != '"' && !s:IsBalanced()
         return "\<BS>"
     endif
 
-    if line[pos-1:pos] =~ s:any_matched_pair
+    if line[pos-1:pos] =~ b:any_matched_pair
         " Deleting an empty character-pair
         return "\<Right>\<BS>\<BS>"
     else
     if pos == len(line)
         " We are at the end of the line
         return "\<Del>"
-    elseif line[pos] == '\' && line[pos+1] =~ s:any_matched_char && (pos < 1 || line[pos-1] != '\')
+    elseif line[pos] == '\' && line[pos+1] =~ b:any_matched_char && (pos < 1 || line[pos-1] != '\')
         " Deleting an escaped matched character
         return "\<Del>\<Del>"
-    elseif line[pos] !~ s:any_matched_char
+    elseif line[pos] !~ b:any_matched_char
         " Erasing a non-special character
         return "\<Del>"
     elseif line[pos] != '"' && !s:IsBalanced()
         return "\<Right>"
     endif
 
-    if line[pos-1:pos] =~ s:any_matched_pair
+    if line[pos-1:pos] =~ b:any_matched_pair
         " Erasing an empty character-pair
         return "\<Left>\<Del>\<Del>"
     else
     let reg = @"
     let c = a:count
     while c > 0
-        if line[pos] == '\' && line[pos+1] =~ s:any_matched_char && (pos < 1 || line[pos-1] != '\')
+        if line[pos] == '\' && line[pos+1] =~ b:any_matched_char && (pos < 1 || line[pos-1] != '\')
             " Erasing an escaped matched character
             let reg = reg . line[pos : pos+1]
             let line = strpart( line, 0, pos ) . strpart( line, pos+2 )
             " Erasing any character inside string or comment
             let reg = reg . line[pos]
             let line = strpart( line, 0, pos ) . strpart( line, pos+1 )
-        elseif pos > 0 && line[pos-1:pos] =~ s:any_matched_pair
+        elseif pos > 0 && line[pos-1:pos] =~ b:any_matched_pair
             if pos > a:startcol
                 " Erasing an empty character-pair
                 let p2 = s:RemoveYankPos()
                 let pos = pos + 1
                 normal! l
             endif
-        elseif line[pos] =~ s:any_matched_char
+        elseif line[pos] =~ b:any_matched_char
             " Character-pair is not empty, don't erase just move inside
             call s:AddYankPos( len(reg) )
             let pos = pos + 1
     let reg = @"
     let c = a:count
     while c > 0 && pos > 0
-        if pos > 1 && line[pos-2] == '\' && line[pos-1] =~ s:any_matched_char && (pos < 3 || line[pos-3] != '\')
+        if pos > 1 && line[pos-2] == '\' && line[pos-1] =~ b:any_matched_char && (pos < 3 || line[pos-3] != '\')
             " Erasing an escaped matched character
             let reg = reg . line[pos-2 : pos-1]
             let line = strpart( line, 0, pos-2 ) . strpart( line, pos )
         elseif s:InsideComment() || ( s:InsideString() && line[pos-1] != '"' )
             let reg = reg . line[pos-1]
             let line = strpart( line, 0, pos-1 ) . strpart( line, pos )
-        elseif line[pos-1:pos] =~ s:any_matched_pair
+        elseif line[pos-1:pos] =~ b:any_matched_pair
             " Erasing an empty character-pair
             let p2 = s:RemoveYankPos()
             let reg = strpart( reg, 0, p2 ) . line[pos-1] . strpart( reg, p2 )
             let reg = reg . line[pos]
             let line = strpart( line, 0, pos-1 ) . strpart( line, pos+1 )
-        elseif line[pos-1] =~ s:any_matched_char
+        elseif line[pos-1] =~ b:any_matched_char
             " Character-pair is not empty, don't erase
             call s:AddYankPos( len(reg) )
         else
             if s:InsideString()
                 let symbol_pos = [l, c]
             elseif symbol_pos == [0, 0]
-                if line[c-1] =~ s:any_closing_char
+                if line[c-1] =~ b:any_closing_char
                     " Skip to the beginning of this sub-expression
                     let symbol_pos = [l, c]
                     normal! %
                     if c2 > 0 && line2[c2-1] =~ s:any_macro_prefix
                         normal! h
                     endif
-                elseif line[c-1] =~ s:any_opening_char
+                elseif line[c-1] =~ b:any_opening_char
                     " Opening delimiter found: stop
                     call setpos( '.', [0, l0, c0, 0] )
                     return [0, 0]
                     let symbol_pos = [l, c]
                 endif
             else
-                if line[c-1] =~ s:any_opening_char || (a:skip_whitespc && line[c-1] =~ '\S' && symbol_end != [0, 0])
+                if line[c-1] =~ b:any_opening_char || (a:skip_whitespc && line[c-1] =~ '\S' && symbol_end != [0, 0])
                     " Previous symbol beginning reached, opening delimiter or second previous symbol starting
                     call setpos( '.', [0, l0, c0, 0] )
                     return [l, c+1]
         if s:InsideString()
             let symbol_pos = [l, c]
         elseif symbol_pos == [0, 0]
-            if line[c-1] =~ s:any_macro_prefix && line[c] =~ s:any_opening_char
+            if line[c-1] =~ s:any_macro_prefix && line[c] =~ b:any_opening_char
                 " Skip to the end of this prefixed sub-expression
                 let symbol_pos = [l, c]
                 normal! l%
-            elseif line[c-1] =~ s:any_opening_char
+            elseif line[c-1] =~ b:any_opening_char
                 " Skip to the end of this sub-expression
                 let symbol_pos = [l, c]
                 normal! %
-            elseif line[c-1] =~ s:any_closing_char
+            elseif line[c-1] =~ b:any_closing_char
                 " Closing delimiter found: stop
                 call setpos( '.', [0, l0, c0, 0] )
                 return [0, 0]
                 let symbol_pos = [l, c]
             endif
         else
-            if line[c-1] =~ s:any_closing_char || (a:skip_whitespc && line[c-1] =~ '\S' && symbol_end != [0, 0])
+            if line[c-1] =~ b:any_closing_char || (a:skip_whitespc && line[c-1] =~ '\S' && symbol_end != [0, 0])
                 " Next symbol ended, closing delimiter or second next symbol starting
                 call setpos( '.', [0, l0, c0, 0] )
                 return [l, c]
 function! s:FindParenNearby()
     let line = getline( '.' )
     let c0 =  col( '.' )
-    if line[c0-1] !~ s:any_openclose_char
+    if line[c0-1] !~ b:any_openclose_char
         " OK, we are not standing on a paren to move, but check if there is one nearby
-        if (c0 < 2 || line[c0-2] !~ s:any_openclose_char) && line[c0] =~ s:any_openclose_char
+        if (c0 < 2 || line[c0-2] !~ b:any_openclose_char) && line[c0] =~ b:any_openclose_char
             normal! l
-        elseif c0 > 1 && line[c0-2] =~ s:any_openclose_char && line[c0] !~ s:any_openclose_char
+        elseif c0 > 1 && line[c0-2] =~ b:any_openclose_char && line[c0] !~ b:any_openclose_char
             normal! h
         endif
     endif
 
     " Skip macro prefix character    
     let c0 =  col( '.' )
-    if line[c0-1] =~ s:any_macro_prefix && line[c0] =~ s:any_opening_char
+    if line[c0-1] =~ s:any_macro_prefix && line[c0] =~ b:any_opening_char
         normal! l
     endif
 
     " If still not standing on a paren then find the next closing one
-    if line[c0-1] !~ s:any_openclose_char
-        call search(s:any_closing_char, 'W')
+    if line[c0-1] !~ b:any_openclose_char
+        call search(b:any_closing_char, 'W')
     endif
 endfunction
 
     let l0 = line( '.' )
     let c0 =  col( '.' )
 
-    if line[c0-1] =~ s:any_opening_char
+    if line[c0-1] =~ b:any_opening_char
         let closing = 0
-    elseif line[c0-1] =~ s:any_closing_char
+    elseif line[c0-1] =~ b:any_closing_char
         let closing = 1
     else
         " Can move only delimiters
     endif
     let line = getline( '.' )
     let c =  col( '.' ) - 1
-    if closing && line[c+1] !~ s:any_wsclose_char
+    if closing && line[c+1] !~ b:any_wsclose_char
         " Insert a space after if needed
         execute "normal! a "
         normal! h
     endif
-    if !closing && c > 0 && line[c-len] !~ s:any_wsopen_char
+    if !closing && c > 0 && line[c-len] !~ b:any_wsopen_char
         " Insert a space before if needed
         if len > 1
             execute "normal! hi "
     let l0 = line( '.' )
     let c0 =  col( '.' )
 
-    if line[c0-1] =~ s:any_opening_char
+    if line[c0-1] =~ b:any_opening_char
         let opening = 1
-    elseif line[c0-1] =~ s:any_closing_char
+    elseif line[c0-1] =~ b:any_closing_char
         let opening = 0
     else
         " Can move only delimiters
     endif
     let line = getline( '.' )
     let c =  col( '.' ) - 1
-    if opening && c > 0 && line[c-len] !~ s:any_wsopen_char
+    if opening && c > 0 && line[c-len] !~ b:any_wsopen_char
         " Insert a space before if needed
         if len > 1
             execute "normal! hi "
             normal! l
         endif
     endif
-    if !opening && line[c+1] !~ s:any_wsclose_char
+    if !opening && line[c+1] !~ b:any_wsclose_char
         " Insert a space after if needed
         execute "normal! a "
         normal! h
     endif
 endfunction
 
-" Find closing of the innermost structure: (...) or [...]
+" Find closing of the innermost structure: (...) or [...] or {...}
 " Return a list where first element is the closing character,
 " second and third is its position (line, column)
 function! s:FindClosing()
     let l = line( '.' )
     let c = col( '.' )
+    let paren = ''
+    let l2 = 0
+    let c2 = 0
+
     call PareditFindClosing( '(', ')', 0 )
     let lp = line( '.' )
     let cp = col( '.' )
+    if [lp, cp] != [l, c]
+        " Do we have a closing ')'?
+        let paren = ')'
+        let l2 = lp
+        let c2 = cp
+    endif
     call setpos( '.', [0, l, c, 0] )
-    call PareditFindClosing( '[', ']', 0 )
-    let lb = line( '.' )
-    let cb = col( '.' )
-    call setpos( '.', [0, l, c, 0] )
-    if [lp, cp] == [l, c] && [lb, cb] == [l, c]
-        " Not found any kind of paren
-        return ['', 0, 0]
-    elseif [lb, cb] == [l, c] || lp < lb || (lp == lb && cp < cb)
-        " The innermost structure is a (...)
-        return [')', lp, cp]
-    else
-        " The innermost structure is a [...]
-        return [']', lb, cb]
+
+    if &ft == 'clojure'
+        call PareditFindClosing( '[', ']', 0 )
+        let lp = line( '.' )
+        let cp = col( '.' )
+        if [lp, cp] != [l, c] && (lp < l2 || (lp == l2 && cp < c2))
+            " Do we have a ']' closer?
+            let paren = ']'
+            let l2 = lp
+            let c2 = cp
+        endif
+        call setpos( '.', [0, l, c, 0] )
+
+        call PareditFindClosing( '{', '}', 0 )
+        let lp = line( '.' )
+        let cp = col( '.' )
+        if [lp, cp] != [l, c] && (lp < l2 || (lp == l2 && cp < c2))
+            " Do we have a '}' even closer?
+            let paren = '}'
+            let l2 = lp
+            let c2 = cp
+        endif
+        call setpos( '.', [0, l, c, 0] )
     endif
+
+    return [paren, l2, c2]
 endfunction
 
 " Split list or string at the cursor position
         " Go back to the beginning of the current symbol
         let c = col('.') - 1
         if getline('.')[c] =~ '\S'
-            if c == 0 || (c > 0 && getline('.')[c-1] =~ s:any_wsopen_char)
+            if c == 0 || (c > 0 && getline('.')[c-1] =~ b:any_wsopen_char)
                 " OK, we are standing on the first character of the symbol
             else
                 normal! b
 
         " First find which kind of paren is the innermost
         let [p, l, c] = s:FindClosing()
-        if p !~ s:any_closing_char
+        if p !~ b:any_closing_char
             " Not found any kind of parens
             return
         endif
 
         if p == ')'
             normal! i) (
+        elseif p == '}'
+            normal! i} {
         else
             normal! i] [
         endif
     endif
 
     "TODO: skip parens in comments
-    let [l0, c0] = searchpos(s:any_matched_char, 'nbW')
-    let [l1, c1] = searchpos(s:any_matched_char, 'ncW')
+    let [l0, c0] = searchpos(b:any_matched_char, 'nbW')
+    let [l1, c1] = searchpos(b:any_matched_char, 'ncW')
     if [l0, c0] == [0, 0] || [l1, c1] == [0, 0]
         return
     endif
     let line0 = getline( l0 )
     let line1 = getline( l1 )
-    if (line0[c0-1] == ')' && line1[c1-1] == '(') || (line0[c0-1] == ']' && line1[c1-1] == '[') || (line0[c0-1] == '"' && line1[c1-1] == '"')
+    let p0 = line0[c0-1]
+    let p1 = line1[c1-1]
+    if (p0 == ')' && p1 == '(') || (p0 == ']' && p1 == '[') || (p0 == '}' && p1 == '{') || (p0 == '"' && p1 == '"')
         if l0 == l1
             " First list ends on the same line where the second list begins
             let line0 = strpart( line0, 0, c0-1 ) . ' ' . strpart( line0, c1 )
 " If standing on a paren then wrap the whole s-expression
 " Stand on the opening paren (if not wrapping in "")
 function! PareditWrap( open, close )
-    if a:open != '"' && getline('.')[col('.') - 1] =~ s:any_openclose_char
+    if a:open != '"' && getline('.')[col('.') - 1] =~ b:any_openclose_char
         execute "normal! " . "v%\<Esc>"
     else
         execute "normal! " . "viw\<Esc>"
 
     " First find which kind of paren is the innermost
     let [p, l, c] = s:FindClosing()
-    if p !~ s:any_closing_char
+    if p !~ b:any_closing_char
         " Not found any kind of parens
         return
     endif
 " =====================================================================
 
 au BufNewFile,BufRead *.lisp call PareditInitBuffer()
+au BufNewFile,BufRead *.cl   call PareditInitBuffer()
 au BufNewFile,BufRead *.clj  call PareditInitBuffer()
 au BufNewFile,BufRead *.scm  call PareditInitBuffer()
+au BufNewFile,BufRead *.rkt  call PareditInitBuffer()
 

File syntax/clojure/slimv-syntax-clojure.vim

 " slimv-syntax-clojure.vim:
 "               Clojure syntax plugin for Slimv
-" Version:      0.8.5
-" Last Change:  01 Jul 2011
+" Version:      0.8.6
+" Last Change:  09 Aug 2011
 " Maintainer:   Tamas Kovacs <kovisoft at gmail dot com>
 " License:      This file is placed in the public domain.
 "               No warranty, express or implied.
 
 runtime syntax/**/lisp.vim
 
-" Add [] to the lisp_rainbow handling
-syn match			 lispSymbol			  contained			   ![^()\[\]'`,"; \t]\+!
+" Add [] and {} to the lisp_rainbow handling
+syn match			 lispSymbol			  contained			   ![^()\[\]{}'`,"; \t]\+!
 syn match			 lispBarSymbol			  contained			   !|..\{-}|!
 if exists("g:lisp_rainbow") && g:lisp_rainbow != 0
     syn region lispParen0           matchgroup=hlLevel0 start="`\=\[" end="\]" skip="|.\{-}|" contains=@lispListCluster,lispParen1 
     syn region lispParen7 contained matchgroup=hlLevel7 start="`\=\[" end="\]" skip="|.\{-}|" contains=@lispListCluster,lispParen8 
     syn region lispParen8 contained matchgroup=hlLevel8 start="`\=\[" end="\]" skip="|.\{-}|" contains=@lispListCluster,lispParen9 
     syn region lispParen9 contained matchgroup=hlLevel9 start="`\=\[" end="\]" skip="|.\{-}|" contains=@lispListCluster,lispParen0
+
+    syn region lispParen0           matchgroup=hlLevel0 start="`\={"  end="}"  skip="|.\{-}|" contains=@lispListCluster,lispParen1 
+    syn region lispParen1 contained matchgroup=hlLevel1 start="`\={"  end="}"  skip="|.\{-}|" contains=@lispListCluster,lispParen2 
+    syn region lispParen2 contained matchgroup=hlLevel2 start="`\={"  end="}"  skip="|.\{-}|" contains=@lispListCluster,lispParen3 
+    syn region lispParen3 contained matchgroup=hlLevel3 start="`\={"  end="}"  skip="|.\{-}|" contains=@lispListCluster,lispParen4 
+    syn region lispParen4 contained matchgroup=hlLevel4 start="`\={"  end="}"  skip="|.\{-}|" contains=@lispListCluster,lispParen5 
+    syn region lispParen5 contained matchgroup=hlLevel5 start="`\={"  end="}"  skip="|.\{-}|" contains=@lispListCluster,lispParen6 
+    syn region lispParen6 contained matchgroup=hlLevel6 start="`\={"  end="}"  skip="|.\{-}|" contains=@lispListCluster,lispParen7 
+    syn region lispParen7 contained matchgroup=hlLevel7 start="`\={"  end="}"  skip="|.\{-}|" contains=@lispListCluster,lispParen8 
+    syn region lispParen8 contained matchgroup=hlLevel8 start="`\={"  end="}"  skip="|.\{-}|" contains=@lispListCluster,lispParen9 
+    syn region lispParen9 contained matchgroup=hlLevel9 start="`\={"  end="}"  skip="|.\{-}|" contains=@lispListCluster,lispParen0
 endif