Commits

Tamas Kovacs committed e64fe43

Version 0.9.7

Keep cursor position on expanding [--more--] in the Inspector. Added [--all---] to Inspector for fetching all parts. Don't explicitly check for pythonXX.dll, rely on has('python'). Require 'swank-repl' for slime version above 2011-12-04 in case contribs are disabled. Identify VimClojure REPL prompt position for paredit (thanks to David Greenberg). Paredit: added <leader><Up> for Splice-killing-backward, <leader><Down> for Splice-killing-forward, <leader>I for Raise. Paredit: added 'Electric Return' feature and new option g:paredit_electric_return. Increased the distance to search for the defun start to 200 lines. Bugfixes: Positioning the cursor at the end of REPL prompt in insert mode. Handle restart/frame number above 999 (thanks to Philipp Marek). Form selection when cursor is next to the opening paren. Indentation of multi-line strings. Indentation of lines with multi-byte characters. Cursor movement while indenting.

  • Participants
  • Parent commits 2991f64

Comments (0)

Files changed (6)

 
 Slimv supports SLIME's debugger, inspector, 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 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.
+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/Raise. 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: 05 Sep 2011
+*paredit.txt*                   Paredit              Last Change: 22 May 2012
 
-Paredit mode for Slimv                                *paredit* *slimv-paredit*
-                               Version 0.8.6
+Paredit Mode for Vim                                  *paredit* *slimv-paredit*
+                               Version 0.9.7
 
 The paredit.vim plugin performs structured editing of s-expressions used in
-the Lisp or Clojure programming language.
+the Lisp, Clojure, Scheme programming languages. It may come as part of Slimv
+but it is also distributed separately as a standalone plugin.
 
 |paredit-mode|               Paredit mode
 |paredit-keys|               Paredit keybindings
 then it will stop at the matched closing parenthesis.
 
 
-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
+Paredit mode is set by default for .lisp, .cl, .clj, cljs, .scm and .rkt files,
+but it is possible to switch it off by putting the following statement in the
 .vimrc file:
 
     let g:paredit_mode = 0
 
     au BufNewFile,BufRead *.arc call PareditInitBuffer()
 
-It is also possible to use the paredit mode alone, without the other parts of
-Slimv. The easiest way to do it is to delete all Slimv related files from the 
-ftplugin directory. If you don't intend to use Slimv's indentation and syntax
-files, then you need to keep only plugin/paredit.vim.
-Another way to prevent Slimv from loading by adding this to your .vimrc file:
-
-    let g:slimv_loaded = 1
-
-Slimv core will not be loaded but paredit will be loaded and assigned to
-.lisp, .clj, .scm, etc files.
+Paredit is part of Slimv, but it is also distributed separately as a standalone
+plugin. If you indend to use the SWANK client and/or Slimv's indentation and
+syntax functions, then please install the Slimv plugin. Otherwise you may want
+to install the Paredit plugin thus omitting other unnecessary files.
 
 
 ===============================================================================
                    outer closing parenthesis, etc, until the closing of the
                    top level form is reached.
                    Inserts ')' when inside comment or string.
+                   If |g:paredit_electric_return| is on then it also re-gathers
+                   electric returns when appropriate.
 
     [              Inserts '[]' and moves the cursor inside. Also adds leading
                    or trailing spaces when needed.
                    outer closing square bracket, etc, until the closing of the
                    top level form is reached.
                    Inserts ']' when inside comment or string.
+                   If |g:paredit_electric_return| is on then it also re-gathers
+                   electric returns when appropriate.
 
     {              Inserts '{}' and moves the cursor inside. Also adds leading
                    or trailing spaces when needed.
                    outer closing curly brace, etc, until the closing of the
                    top level form is reached.
                    Inserts '}' when inside comment or string.
+                   If |g:paredit_electric_return| is on then it also re-gathers
+                   electric returns when appropriate.
 
     "              When outside of string, inserts '""' and moves the cursor
                    inside. When inside string then moves to the closing '"'.                   
                    about to delete the closing part of the matched character
                    with nothing inside, then the whole empty list is removed.
 
+    <Enter>        If |g:paredit_electric_return| is on then insert an
+                   "electric return", i.e. create an empty line by inserting
+                   two newline characters.
+                   
 
 Normal Mode:
 
                    Pressing '<' when standing on a '(' makes the s-expression
                    to the left of the '(' coming into the current list.
                    For example pressing <Leader>< at position marked with |:
-                       (aaa bbb|)        --->    (aaa) bbb
-                       aaa |(bbb)        --->    (aaa bbb)
+                       (aaa bbb|)        --->    (aaa|) bbb
+                       aaa |(bbb)        --->    |(aaa bbb)
 
     <Leader>>      If standing on a delimiter (parenthesis or square bracket)
                    then moves it to the right by slurping or barfing the
                    Pressing '>' when standing on a ')' makes the s-expression
                    to the right of the ')' coming into the current list.
                    For example pressing <Leader>< at position marked with |:
-                       (aaa|) bbb        --->    (aaa bbb)
-                       |(aaa bbb)        --->    aaa (bbb)
+                       (aaa|) bbb        --->    (aaa bbb|)
+                       |(aaa bbb)        --->    aaa |(bbb)
 
     <Leader>J      Join two subsequent lists or strings. The first one must end
                    before the cursor, the second one must start after the
                    cursor position.
                    For example pressing <Leader>J at position marked with |:
-                       (aaa)| (bbb)      --->    (aaa bbb)
-                       "aaa"| "bbb"      --->    "aaa bbb"
+                       (aaa)| (bbb)      --->    (aaa |bbb)
+                       "aaa"| "bbb"      --->    "aaa |bbb"
 
     <Leader>O      Split ("Open") current list or string at the cursor position.
                    Opposite of Join. Key O is selected because for the original
                    Vim mapping J and O are also kind of opposites.
                    For example pressing <Leader>O at position marked with |:
-                       (aaa |bbb)        --->    (aaa) (bbb)
-                       "aaa|bbb"         --->    "aaa" "bbb"
+                       (aaa |bbb)        --->    (aaa) |(bbb)
+                       "aaa|bbb"         --->    "aaa" |"bbb"
 
     <Leader>W      Wrap the current symbol in a pair of parentheses. The cursor
     <Leader>w(     is then positioned on the opening parenthesis, as wrapping
                    the symbol as parameter, so by pressing "a" one can enter
                    the function name right after the newly inserted "(".
                    For example pressing <Leader>W at position marked with |:
-                       (aaa b|bb ccc)    --->    (aaa (bbb) ccc)
+                       (aaa b|bb ccc)    --->    (aaa |(bbb) ccc)
 
     <Leader>w[     Wrap the current symbol in a pair of square brackets,
                    similarly to <Leader>W.
                    For example pressing <Leader>w[ at position marked with |:
-                       (aaa b|bb ccc)    --->    (aaa [bbb] ccc)
+                       (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)
+                       (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 |:
-                       (aaa b|bb ccc)    --->    (aaa "bbb" ccc)
+                       (aaa b|bb ccc)    --->    (aaa "bbb|" ccc)
 
     <Leader>S      Splice the current list into the containing list, i.e.
                    remove the opening and closing parens. Opposite of wrap.
                    For example pressing <Leader>S at position marked with |:
-                       (aaa (b|bb) ccc)  --->    (aaa bbb ccc)
+                       (aaa (b|bb ccc) ddd)  --->    (aaa |bbb ccc ddd)
+
+    <Leader><Up>   Splice the current list into the containing list by deleting
+                   everything backward from the cursor position up to the
+                   opening paren.
+                   For example pressing <Leader><Up> at position marked with |:
+                       (aaa (bbb |ccc) ddd)  --->    (aaa |ccc ddd)
+
+    <Leader><Down> Splice the current list into the containing list by deleting
+                   everything forward from the cursor position up to the
+                   closing paren.
+                   For example pressing <Leader><Down> at position marked with |:
+                       (aaa (bbb| ccc) ddd)  --->    (aaa |bbb ddd)
+
+    <Leader>I      Raise the current symbol, i.e. replace the current list with
+                   the current symbol by deleting everything else (except the
+                   symbol) in the list, including the eclosing pair of parens.
+                   For example pressing <Leader>I at position marked with |:
+                       (aaa (b|bb ccc) ddd)  --->    (aaa |bbb ddd)
 
     x  or  <Del>   When about to delete a (, ), [, ], or " and there are other
                    characters inside, then just skip it to the right. When
 ===============================================================================
 PAREDIT OPTIONS                                               *paredit-options*
 
+|g:paredit_electric_return|  If nonzero, electric return feature is enabled.
+
 |g:paredit_leader|           Custom <Leader> setting for Paredit.
+
 |g:paredit_matchlines|       Number of lines to look backward and forward
                              when checking if the current form is balanced.
 
                              Vim commands that are not frequently used.
 
 
+                                                    *g:paredit_electric_return*
+If nonzero then "electric return" feature is enabled. This means that when an
+<Enter> is pressed before a closing paren in insert mode, paredit will actually
+insert two newlines creating an empty line. The extra newline is consumed at
+pressing the next closing paren. This feature allows linewise editing of the
+subform entered in the next (empty) line.
+In other words <Enter> "opens" parenthetical expressions while editing, ')'
+"closes" them.
+Please note that electric return is disabled for the REPL buffer where
+<Enter> is used to send the command line to the swank server for evaluation.
+
+Please find a video demonstration of the electric return feature here:
+http://img8.imageshack.us/img8/9479/openparen.gif
+
                                                              *g:paredit_leader*
 This option allows a custom <Leader> setting for the Paredit keybindings.
 By default it has the same value as |mapleader|. If neither g:paredit_leader
 top level form is balanced in paredit mode. Default is 100.
 
                                                                *g:paredit_mode*
-If nonzero then paredit mode is switched on, i.e. Slimv tries to keep the
-balanced state of parens.
+If nonzero then paredit mode is switched on, i.e. the plugin tries to keep the
+balanced state of parens. This is the default behaviour.
 
                                                           *g:paredit_shortmaps*
 If nonzero, paredit is remapping some one-letter normal mode Vim commands that

File doc/slimv.txt

-*slimv.txt*                    Slimv                 Last Change: 31 Mar 2012
+*slimv.txt*                    Slimv                 Last Change: 29 May 2012
 
 Slimv                                                                  *slimv*
-                               Version 0.9.6
+                               Version 0.9.7
 
 The Superior Lisp Interaction Mode for Vim.
 This plugin is aimed to help Lisp development by interfacing between Vim and
 Pressing <Leader>q also exits the Inspector.
 
 If the object is too big to be fully displayed, this is signaled by the
-[--more--] text. When pressing Enter on the line containing [--more--] then
-the next part of the inspected object is queried from the swank server and
-displayed in the Inspect buffer.
+[--more--] and [--all---] texts. When pressing Enter on the line containing
+[--more--] then the next part of the inspected object is queried from the
+swank server and displayed in the Inspect buffer.
+When pressing Enter on the [--all---] line then all parts of the inspected
+object are fetched recursively up to the timeout defined by |g:slimv_timeout|.
+Pressing <Esc> stops the recursive fetching process.
 
 
 If debugger is activated and the cursor is placed on a frame line in the
      It is also possible to save a log of the communication between Slimv and
      the swank server by setting g:swank_log=1 in the .vimrc.
 
+- Q: I get SLDB error messages related to some contributed modules of Slime, e.g.
+     "The loaded code expects an incompatible layout for class SB-PRETTY:PRETTY-STREAM."
+- A: Some contribs are known to be incompatible with some other Lisp
+     packages. Try to disable contribs in slime/start-swank.lisp by setting
+     :load-contribs to 'nil'.
+
 - Q: Why is SLIME functionality XYZ missing from Slimv?
 - A: Not all SLIME functions are implemented in the SWANK client, however
      the list of these functions keep growing.  Maybe future releases will
 ===============================================================================
 CHANGE LOG                                                    *slimv-changelog*
 
+0.9.7  - Keep cursor position on expanding [--more--] in the Inspector.
+       - Added [--all---] to Inspector for fetching all parts.
+       - Don't explicitly check for pythonXX.dll, rely on has('python').
+       - Require 'swank-repl' for slime version above 2011-12-04 in case
+         contribs are disabled.
+       - Identify VimClojure REPL prompt position for paredit (thanks to
+         David Greenberg).
+       - Paredit: added <leader><Up> for Splice-killing-backward,
+         <leader><Down> for Splice-killing-forward, <leader>I for Raise.
+       - Paredit: added 'Electric Return' feature and new option
+         g:paredit_electric_return.
+       - Increased the distance to search for the defun start to 200 lines.
+       - Bugfix: positioning the cursor at the end of REPL prompt in insert mode.
+       - Bugfix: handle restart/frame number above 999 (thanks to Philipp Marek).
+       - Bugfix: form selection when cursor is next to the opening paren.
+       - Bugfix: indentation of multi-line strings.
+       - Bugfix: indentation of lines with multi-byte characters.
+       - Bugfix: cursor movement while indenting.
+
 0.9.6  - Perform indenting when <Tab> pressed on whitespace.
        - Added support for newer swank message length counting in bytes.
        - Updated Lisp swank server to version 2012-03-06.
 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, Chris Cahoon, Mats Rauhala, Oleg Terenchuk,
-Andrew Lyon, Andrew Smirnoff, Brett Kosinski for additional notes and
-contributions.
+Andrew Lyon, Andrew Smirnoff, Brett Kosinski, David Greenberg 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: :)

File ftplugin/slimv.vim

 " slimv.vim:    The Superior Lisp Interaction Mode for VIM
-" Version:      0.9.6
-" Last Change:  27 Mar 2012
+" Version:      0.9.7
+" Last Change:  15 May 2012
 " Maintainer:   Tamas Kovacs <kovisoft at gmail dot com>
 " License:      This file is placed in the public domain.
 "               No warranty, express or implied.
 let s:current_win = -1                                    " Swank action was requested from this window
 let s:skip_sc = 'synIDattr(synID(line("."), col("."), 0), "name") =~ "[Ss]tring\\|[Cc]omment"'
                                                           " Skip matches inside string or comment 
-let s:frame_def = '^\s\{0,2}\d\{1,3}:'                    " Regular expression to match SLDB restart or frame identifier
+let s:skip_q = 'getline(".")[col(".")-2] == "\\"'         " Skip escaped double quote characters in matches
+let s:frame_def = '^\s\{0,2}\d\{1,}:'                     " Regular expression to match SLDB restart or frame identifier
 let s:spec_indent = 'flet\|labels\|macrolet\|symbol-macrolet'
                                                           " List of symbols need special indenting
 let s:spec_param = 'defmacro'                             " List of symbols with special parameter list
     let &shortmess=saved
 endfunction
 
+" Go to the end of buffer, make sure the cursor is positioned
+" after the last character of the buffer when in insert mode
+function s:EndOfBuffer()
+    normal! G$
+    call cursor( line('$'), 99999 )
+endfunction
+
 " Position the cursor at the end of the REPL buffer
 " Optionally mark this position in Vim mark 's'
 function! SlimvEndOfReplBuffer()
     if line( '.' ) >= b:repl_prompt_line - 1
         " Go to the end of file only if the user did not move up from here
-        normal! G$
+        call s:EndOfBuffer()
     endif
 endfunction
 
 function! SlimvTimer()
     call SlimvRefreshReplBuffer()
     if mode() == 'i' || mode() == 'I' || mode() == 'r' || mode() == 'R'
-        " Put '<Insert>' twice into the typeahead buffer, which should not do anything
-        " just switch to replace/insert mode then back to insert/replace mode
-        " But don't do this for readonly buffers
         if bufname('%') != g:slimv_sldb_name && bufname('%') != g:slimv_inspect_name && bufname('%') != g:slimv_threads_name
+            " Put '<Insert>' twice into the typeahead buffer, which should not do anything
+            " just switch to replace/insert mode then back to insert/replace mode
+            " But don't do this for readonly buffers
             call feedkeys("\<insert>\<insert>")
         endif
     else
 
     syn match Type /^\[\d\+\]/
     syn match Type /^\[<<\]/
-    syn match Type /^\[--more--\]$/
+    syn match Type /^\[--....--\]$/
 endfunction
 
 " Open a new Threads buffer
         normal! l
         let c = c + 1
     endwhile
+    normal! va(
     let p1 = getpos('.')
-    normal! va(o
+    normal! o
     let p2 = getpos('.')
     if firstchar != '(' && p1[1] == p2[1] && (p1[2] == p2[2] || p1[2] == p2[2]+1)
         " Empty selection and no paren found, select current word instead
 " Find starting '(' of a top level form
 function! SlimvFindDefunStart()
     let l = line( '.' )
-    let matchb = max( [l-100, 1] )
+    let matchb = max( [l-200, 1] )
     while searchpair( '(', '', ')', 'bW', s:skip_sc, matchb )
     endwhile
 endfunction
 function! SlimvConnectSwank()
     if !s:python_initialized
         if ! has('python')
-            call SlimvErrorWait( 'Vim is compiled without the Python feature. Unable to run SWANK client.' )
+            call SlimvErrorWait( 'Vim is compiled without the Python feature or Python is not installed. Unable to run SWANK client.' )
             return 0
         endif
-        if g:slimv_windows || g:slimv_cygwin
-            " Verify that Vim is compiled with Python and Python is properly installed
-            let v = ''
-            redir => v
-            silent ver
-            redir END
-            let pydll = matchstr( v, '\cpython..\.dll' )
-            if ! executable( pydll )
-                call SlimvErrorWait( pydll . ' not found. Unable to run SWANK client.' )
-                return 0
-            endif
-        endif
         python import vim
         execute 'pyfile ' . g:swank_path
         let s:python_initialized = 1
         while s:swank_version == '' && localtime()-starttime < g:slimv_timeout
             call SlimvSwankResponse()
         endwhile
+        if s:swank_version >= '2011-12-04'
+            python swank_require('swank-repl')
+            call SlimvSwankResponse()
+        endif
         if s:swank_version >= '2008-12-23'
             call SlimvCommandGetResponse( ':create-repl', 'python swank_create_repl()', g:slimv_timeout )
         endif
     return end
 endfunction
 
+" Some multi-byte characters screw up the built-in lispindent()
+" This function is a wrapper that tries to fix it
+" TODO: implement custom indent procedure and omit lispindent()
+function SlimvLispindent( lnum )
+    set lisp
+    let li = lispindent( a:lnum )
+    set nolisp
+    let backline = max([a:lnum-g:slimv_indent_maxlines, 1])
+    let oldpos = winsaveview()
+    normal! 0
+    " Find containing form
+    let [lhead, chead] = searchpairpos( '(', '', ')', 'bW', s:skip_sc, backline )
+    if lhead == 0
+        " No containing form, lispindent() is OK
+        call winrestview( oldpos )
+        return li
+    endif
+    " Find outer form
+    let [lparent, cparent] = searchpairpos( '(', '', ')', 'bW', s:skip_sc, backline )
+    call winrestview( oldpos )
+    if lparent == 0 || lhead != lparent
+        " No outer form or starting above inner form, lispindent() is OK
+        return li
+    endif
+    " Count extra bytes before the function header
+    let header = strpart( getline( lparent ), 0 )
+    let total_extra = 0
+    let extra = 0
+    let c = 0
+    while a:lnum > 0 && c < chead-1
+        let bytes = byteidx( header, c+1 ) - byteidx( header, c )
+        if bytes > 1
+            let total_extra = total_extra + bytes - 1
+            if c >= cparent && extra < 10
+                " Extra bytes in the outer function header
+                let extra = extra + bytes - 1
+            endif
+        endif
+        let c = c + 1
+    endwhile
+    if total_extra == 0  
+        " No multi-byte character, lispindent() is OK
+        return li
+    endif
+    " In some cases ending spaces add up to lispindent() if there are multi-byte characters
+    let ending_sp = len( matchstr( getline( lparent ), ' *$' ) )
+    " Determine how wrong lispindent() is based on the number of extra bytes
+    " These values were determined empirically
+    if lparent == a:lnum - 1
+        " Function header is in the previous line
+        if extra == 0 && total_extra > 1
+            let ending_sp = ending_sp + 1
+        endif
+        return li + [0, 1, 0, -3, -3, -3, -5, -5, -7, -7, -8][extra] - ending_sp
+    else
+        " Function header is in an upper line
+        if extra == 0 || total_extra == extra
+            let ending_sp = 0
+        endif
+        return li + [0, 1, 0, -2, -2, -3, -3, -3, -3, -3, -3][extra] - ending_sp
+    endif
+endfunction
+
 " Return Lisp source code indentation at the given line
 function! SlimvIndent( lnum )
     if a:lnum <= 1
         " Hit the start of the file, use zero indent.
         return 0
     endif
+    let oldpos = winsaveview()
+    let linenum = a:lnum
+
+    " Handle multi-line string
+    let plen = len( getline( pnum ) )
+    if synIDattr( synID( pnum, plen, 0), 'name' ) =~ '[Ss]tring' && getline(pnum)[plen-1] != '"'
+        " Previous non-blank line ends with an unclosed string, so this is a multi-line string
+        let [l, c] = searchpairpos( '"', '', '"', 'bnW', s:skip_q )
+        if l == pnum && c > 0
+            " Indent to the opening double quote (if found)
+            return c
+        else
+            return SlimvLispindent( linenum )
+        endif
+    endif
+    if synIDattr( synID( pnum, 1, 0), 'name' ) =~ '[Ss]tring' && getline(pnum)[0] != '"'
+        " Previous non-blank line is the last line of a multi-line string
+        call cursor( pnum, 1 )
+        " First find the end of the multi-line string (omit \" characters)
+        let [lend, cend] = searchpos( '[^\\]"', 'nW' )
+        if lend > 0 && strpart(getline(lend), cend+1) =~ '(\|)\|\[\|\]\|{\|}'
+            " Structural change after the string, no special handling
+        else
+            " Find the start of the multi-line string (omit \" characters)
+            let [l, c] = searchpairpos( '"', '', '"', 'bnW', s:skip_q )
+            if l > 0 && strpart(getline(l), 0, c-1) =~ '^\s*$'
+                " Nothing else before the string: indent to the opening "
+                call winrestview( oldpos )
+                return c - 1
+            endif
+            if l > 0
+                " Pretend that we are really after the first line of the multi-line string
+                let pnum = l
+                let linenum = l + 1
+            endif
+        endif
+        call winrestview( oldpos )
+    endif
 
     " Handle special indentation style for flet, labels, etc.
     " When searching for containing forms, don't go back
     " more than g:slimv_indent_maxlines lines.
     let backline = max([pnum-g:slimv_indent_maxlines, 1])
-    let oldpos = winsaveview()
     let indent_keylists = g:slimv_indent_keylists
     " Find beginning of the innermost containing form
     normal! 0
                 endif
             endif
         endif
-        " Restore all cursor movements
-        call winrestview( oldpos )
     endif
 
+    " Restore all cursor movements
+    call winrestview( oldpos )
+
     " Check if the current form started in the previous nonblank line
     if l == pnum
         " Found opening paren in the previous line
         endif
     endif
 
-    " Use default Lisp indening
-    set lisp
-    let li = lispindent(a:lnum)
-    set nolisp
-    let line = strpart( getline(a:lnum-1), li-1 )
+    " Use default Lisp indenting
+    let li = SlimvLispindent(linenum)
+    let line = strpart( getline(linenum-1), li-1 )
     let gap = matchend( line, '^(\s\+\S' )
     if gap >= 0
         " Align to the gap between the opening paren and the first atom
     endif
 
     if line[0] == '['
-        if line =~ '^[--more--\]$'
+        if line =~ '^\[--more--\]$'
             " More data follows, fetch next part
             call SlimvCommand( 'python swank_inspector_range()' )
             call SlimvRefreshReplBuffer()
             return
+        elseif line =~ '^\[--all---\]$'
+            " More data follows, fetch all parts
+            echon "\rFetching all entries, please wait..."
+            let b:inspect_more = -1
+            call SlimvCommand( 'python swank_inspector_range()' )
+            call SlimvRefreshReplBuffer()
+            let starttime = localtime()
+            while b:inspect_more < 0 && localtime()-starttime < g:slimv_timeout
+                " Wait for the first swank_inspector_range() call to finish
+                call SlimvRefreshReplBuffer()
+            endwhile
+            let starttime = localtime()
+            while b:inspect_more > 0 && localtime()-starttime < g:slimv_timeout
+                " There are more parts to fetch (1 entry is usually 4 parts)
+                echon "\rFetching all entries, please wait [" . (b:inspect_more / 4) . "]"
+                call SlimvCommand( 'python swank_inspector_range()' )
+                call SlimvRefreshReplBuffer()
+                if getchar(1)
+                    " User is impatient, stop fetching
+                    break
+                endif
+            endwhile
+            if b:inspect_more > 0
+                echon "\rFetch exhausted. Select [--all---] to resume."
+            else
+                echon "\rSuccessfully fetched all entries."
+            endif
+            return
         elseif line[0:3] == '[<<]'
             " Pop back up in the inspector
             let item = '-1'
         let save_ve = &virtualedit
         set virtualedit=onemore
         " Display only if entering the first space after a keyword
-        let matchb = max( [l-100, 1] )
+        let matchb = max( [l-200, 1] )
         let [l0, c0] = searchpairpos( '(', '', ')', 'nbW', s:skip_sc, matchb )
         if l0 > 0
             " Found opening paren, let's find out the function name
     endif
     if bufnr( "%" ) == bufnr( g:slimv_repl_name )
         " If this is the REPL buffer then go to EOF
-        normal! G$
+        call s:EndOfBuffer()
     endif
     call SlimvEval( lines )
 endfunction
         let s:swank_form = SlimvGetSelection()
         if bufnr( "%" ) == bufnr( g:slimv_repl_name )
             " If this is the REPL buffer then go to EOF
-            normal! G$
+            call s:EndOfBuffer()
         endif
         call SlimvCommandUsePackage( 'python swank_macroexpand("s:swank_form")' )
     endif
         let s:swank_form = SlimvGetSelection()
         if bufnr( "%" ) == bufnr( g:slimv_repl_name )
             " If this is the REPL buffer then go to EOF
-            normal! G$
+            call s:EndOfBuffer()
         endif
         call SlimvCommandUsePackage( 'python swank_macroexpand_all("s:swank_form")' )
     endif

File ftplugin/swank.py

 #
 # SWANK client for Slimv
 # swank.py:     SWANK client code for slimv.vim plugin
-# Version:      0.9.6
-# Last Change:  25 Mar 2012
+# Version:      0.9.7
+# Last Change:  20 Apr 2012
 # Maintainer:   Tamas Kovacs <kovisoft at gmail dot com>
 # License:      This file is placed in the public domain.
 #               No warranty, express or implied.
     """
     global inspect_content
 
-    cur_line = vim.eval('line(".")')
+    vim.command('let oldpos=winsaveview()')
     buf = vim.current.buffer
     # First 2 lines are filled in swank_parse_inspect()
     buf[2:] = []
                 linestart = len(lst)
     if int(istate) > int(end):
         # Swank returns end+1000 if there are more entries to request
-        # Save current range for the next request
-        vc = ":let b:range_start=" + start
-        vim.command(vc)
-        vc = ":let b:range_end=" + end
-        vim.command(vc)
         if linestart >= 0 and linestart < len(lst) and (len(lst[linestart]) == 0 or lst[linestart][0] != '['):
             lst[linestart:] = "[--more--]"
         else:
             lst.append("\n[--more--]")
+        lst.append("\n[--all---]")
     buf = vim.current.buffer
     buf.append([''])
     buf.append("".join(lst).split("\n"))
     buf.append(['', '[<<]'])
-    vim.command('normal! ' + cur_line + 'G')
     vim.command('normal! 3G0')
     vim.command('call SlimvHelp(2)')
-    vim.command('normal! j')
+    vim.command('call winrestview(oldpos)')
+    if int(istate) > int(end):
+        # There are more entries to request
+        # Save current range for the next request
+        vim.command("let b:range_start=" + start)
+        vim.command("let b:range_end=" + end)
+        vim.command("let b:inspect_more=" + end)
+    else:
+        # No ore entries left
+        vim.command("let b:inspect_more=0")
 
 def swank_parse_inspect(struct):
     """

File plugin/paredit.vim

 " paredit.vim:
 "               Paredit mode for Slimv
-" Version:      0.9.6
-" Last Change:  13 Mar 2012
+" Version:      0.9.7
+" Last Change:  22 May 2012
 " Maintainer:   Tamas Kovacs <kovisoft at gmail dot com>
 " License:      This file is placed in the public domain.
 "               No warranty, express or implied.
     endif
 endif
 
+" Use 'Electric Return', i.e. add double newlines if enter pressed before a closing paren
+if !exists( 'g:paredit_electric_return' )
+    let g:paredit_electric_return = 1
+endif
+
 " =====================================================================
 "  Other variable definitions
 " =====================================================================
     if g:paredit_mode
         " Paredit mode is on: add buffer specific keybindings
         inoremap <buffer> <expr>   (            PareditInsertOpening('(',')')
-        inoremap <buffer> <expr>   )            PareditInsertClosing('(',')')
+        inoremap <buffer> <silent> )            <C-O>:<C-U>call PareditInsertClosing('(',')')<CR>
         inoremap <buffer> <expr>   "            PareditInsertQuotes()
         inoremap <buffer> <expr>   <BS>         PareditBackspace(0)
         inoremap <buffer> <expr>   <Del>        PareditDel()
         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>"
+        " Spliec s-expression killing backward/forward
+        execute 'nmap     <buffer> <silent> ' . g:paredit_leader.'<Up>    d[(,S'
+        execute 'nmap     <buffer> <silent> ' . g:paredit_leader.'<Down>  d])%,S'
+        execute 'nmap     <buffer> <silent> ' . g:paredit_leader.'I   :<C-U>call PareditRaise()<CR>'
         if &ft == 'clojure'
             inoremap <buffer> <expr>   [            PareditInsertOpening('[',']')
-            inoremap <buffer> <expr>   ]            PareditInsertClosing('[',']')
+            inoremap <buffer> <silent> ]            <C-O>:<C-U>call PareditInsertClosing('[',']')<CR>
             inoremap <buffer> <expr>   {            PareditInsertOpening('{','}')
-            inoremap <buffer> <expr>   }            PareditInsertClosing('{','}')
+            inoremap <buffer> <silent> }            <C-O>:<C-U>call PareditInsertClosing('{','}')<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.'S  :<C-U>call PareditSplice()<CR>'
         endif
+
+        if g:paredit_electric_return && !s:IsReplBuffer()
+            " No electric return in the REPL buffer
+            inoremap <buffer> <expr>   <CR>         PareditEnter()
+        endif
     else
         " Paredit mode is off: remove keybindings
         silent! iunmap <buffer> (
             silent! iunmap <buffer> {
             silent! iunmap <buffer> }
         endif
+        if mapcheck( "<CR>", "i" ) == "PareditEnter()"
+            " Remove only if we have added this mapping
+            silent! iunmap <buffer> <CR>
+        endif
     endif
 endfunction
 
     return s:SynIDMatch( '[Ss]tring', l, c, 0 )
 endfunction
 
-" Is this a Slimv REPL buffer?
+" Is this a Slimv or VimClojure REPL buffer?
 function! s:IsReplBuffer()
     if exists( 'g:slimv_repl_name' )
         return bufnr( g:slimv_repl_name ) == bufnr( '%' )
+    elseif exists( 'b:vimclojure_repl' )
+        return 1
     else
         return 0
     endif
 endfunction
 
-" Get Slimv REPL buffer last command prompt position
+" Get Slimv or VimClojure REPL buffer last command prompt position
 " Return [0, 0] if this is not the REPL buffer
 function! s:GetReplPromptPos()
     if !s:IsReplBuffer()
         return [0, 0]
     endif
-    return [ b:repl_prompt_line, b:repl_prompt_col ]
+    if exists( 'b:vimclojure_repl')
+        let cur_pos = getpos( '.' )
+        call cursor( line( '$' ), 1)
+        call cursor( line( '.' ), col( '$') )
+        call search( b:vimclojure_namespace . '=>', 'bcW' )
+        let target_pos = getpos( '.' )[1:2]
+        call setpos( '.', cur_pos )
+        return target_pos
+    else
+        return [ b:repl_prompt_line, b:repl_prompt_col ]
+    endif
 endfunction
 
 " Is the current top level form balanced, i.e all opening delimiters
 " Insert closing type of a paired character, like ) or ].
 function! PareditInsertClosing( open, close )
     if !g:paredit_mode || s:InsideComment() || s:InsideString() || !s:IsBalanced()
-        return a:close
+        call feedkeys( a:close, 'n' )
+        return
     endif
     let line = getline( '.' )
     let pos = col( '.' ) - 1
     if pos > 0 && line[pos-1] == '\' && (pos < 2 || line[pos-2] != '\')
         " About to enter a \) or \]
-        return a:close
+        call feedkeys( a:close, 'n' )
+        return
     elseif line[pos] == a:close
-        return "\<Right>"
-    else
-        let open  = escape( a:open , '[]' )
-        let close = escape( a:close, '[]' )
-        return "\<C-O>:call searchpair('" . open . "','','" . close . "','W','" . s:skip_sc . "')\<CR>\<Right>"
-        "TODO: indent after going to closing character
+        if g:paredit_electric_return && line =~ '^\s*)'
+            " Re-gather electric returns in the current line
+            normal! kJl
+        endif
+        " Already have the desired character, move right
+        call feedkeys( "\<Right>", 'n' )
+        return
     endif
+    let open  = escape( a:open , '[]' )
+    let close = escape( a:close, '[]' )
+    let newpos = searchpairpos( open, '', close, 'nW', s:skip_sc )
+    if g:paredit_electric_return && newpos[0] > line('.')
+        " Closing paren is in a line below, check if there are electric returns to re-gather
+        let nextline = getline( line('.') + 1 )
+        let nextline = substitute( nextline, '\s', '', 'g' )
+        if len(nextline) > 0 && nextline[0] == ')'
+            " Re-gather electric returns in the line of the closing ')'
+            call setline( line('.'), substitute( line, '\s*$', '', 'g' ) )
+            normal! Jl
+            call feedkeys( "\<Right>", 'n' )
+            return
+        endif
+        if len(nextline) > 0 && nextline[0] =~ '\]\|}' && &ft == 'clojure' 
+            " Re-gather electric returns in the line of the closing ']' or '}'
+            call setline( line('.'), substitute( line, '\s*$', '', 'g' ) )
+            normal! Jxl
+            call feedkeys( "\<Right>", 'n' )
+            return
+        endif
+    elseif g:paredit_electric_return && line =~ '^\s*)'
+        " Re-gather electric returns in the current line
+        normal! kJl
+        call feedkeys( "\<Right>", 'n' )
+        return
+    endif
+    if newpos[0] > 0
+        call setpos( '.', [0, newpos[0], newpos[1], 0] )
+        call feedkeys( "\<Right>", 'n' )
+    endif
+    "TODO: indent after going to closing character
 endfunction
 
 " Insert an (opening or closing) double quote
     endif
 endfunction
 
+" Handle <Enter> keypress, insert electric return if applicable
+function! PareditEnter()
+    let line = getline( '.' )
+    let pos = col( '.' ) - 1
+    if g:paredit_electric_return && pos > 0 && line[pos] =~ b:any_closing_char && !s:InsideString() && s:IsBalanced()
+        " Electric Return
+        return "\<CR>\<CR>\<Up>"
+    else
+        " Regular Return
+        return "\<CR>"
+    endif
+endfunction
+
 " Handle <BS> keypress
 function! PareditBackspace( repl_mode )
     let [lp, cp] = s:GetReplPromptPos()
     endif
 endfunction
 
+" Raise: replace containing form with the current symbol or sub-form
+function! PareditRaise()
+    if getline('.')[col('.')-1] =~ b:any_openclose_char
+        " Raise sub-form and re-indent
+        normal! y%d%dab
+        normal! "0P=%
+    else
+        " Raise symbol
+        normal! yiwdab
+        normal! "0Pb
+    endif
+endfunction
 
 " =====================================================================
 "  Autocommands