Tamas Kovacs avatar Tamas Kovacs committed 584117d

Version 0.9.3

Start Swank server in virtual terminal when running in GNU screen on Linux (thanks to Oleg Terenchuk). Reuse a window for slimv also when there are three or more windows open. Don't go to end of REPL buffer if user moved the cursor away from EOF. Use xdg-open for default browser in Linux. Removed option g:slimv_python. Added option g:slimv_repl_max_len for limiting the number of lines in the REPL buffer. Added option g:slimv_preferred to choose preferred lisp implementation. Query additional parts of big inspected object upon pressing Enter on [--more--]. Thread List is displayed and handled in a separate Threads buffer. Bugfixes: Window navigation problems between source/REPL/SLDB/etc. Error messages when Swank server window is closed. Return control to vim after starting browser defined by g:slimv_browser_cmd. Fixed indentation of arguments before &body argument. Autocomplete for dotted package/namespace names. Indentation of aif.

Comments (0)

Files changed (7)

-*slimv.txt*                    Slimv                 Last Change: 27 Oct 2011
+*slimv.txt*                    Slimv                 Last Change: 22 Dec 2011
 
 Slimv                                                                  *slimv*
-                               Version 0.9.2
+                               Version 0.9.3
 
 The Superior Lisp Interaction Mode for Vim.
 This plugin is aimed to help Lisp development by interfacing between Vim and
     This will generate all the help tags for any file located in the doc
     directory.
   - Enter path definitions into your vimrc (if the default values are not
-    valid for your Vim/Python/Lisp installation).
+    valid for your Vim/Lisp installation).
     See |slimv-configuration| below on how to do this.
 
 
 |g:slimv_package|            If nonzero, Slimv package/namespace handling is
                              switched on.
 
-|g:slimv_python|             Path for the Python interpreter.
+|g:slimv_preferred|          Name of the preferred lisp implementation.
+
+|g:slimv_repl_max_len|       Maximum number of lines in the REPL buffer.
 
 |g:slimv_repl_name|          Name of the REPL buffer.
 
 
 |g:slimv_swank_scheme|       Command used to start the Scheme SWANK server.
 
+|g:slimv_threads_name|       Name of the Threads buffer.
+
 |g:slimv_timeout|            Timeout defined for starting up or connecting
                              to the SWANK server.
 
 
 Note: Most options require to restart the Vim session when modified.
 
-Slimv tries to autodetect the Python and Lisp installation directories,
-however the algorithm is not very sophisticated.
+Slimv tries to autodetect the Lisp installation directory, however the
+algorithm is not very sophisticated.
 If the installation directories are put in the path, then the autodetection
 should find them (this is usually the case on Linux). Otherwise (on Windows)
 some frequently used directories are searched under C:\ and C:\Program Files.
-For a minimum, Slimv needs to know the path of the existing Python and Lisp
-installations, so if autodetection does not work for you, then set the
-following global variables in your vimrc.
+For a minimum, Slimv needs to know the path of the existing Lisp installation,
+so if autodetection does not work for you, then set the following global
+variables in your vimrc.
 
 Note: On Windows use the / (slash) character instead of \ (backslash) as the
       directory separator to avoid any incidental character escaping problems
       while the paths are beeing passed between the Slimv processes.
       On Linux this is not an issue.
 
-                                                               *g:slimv_python*
-This is the installation path of the Python interpreter.
-Normally the Python path is autodetected, but sometimes autodetection fails
-and you need to set up the path in your .vimrc file explicitly.
-If the Python path contains space characters then either the spaces should be
-escaped (Linux) or the short 8.3 filename format should be used (Windows).
-Enclosing the full Python path in double quotes may also work, but this depends
-on the command string handling of the console command used (xterm/cmd.exe/etc).
-Example:
-    let g:slimv_python = 'C:/MyPythonDir/python.exe'
-
                                                                  *g:slimv_lisp*
 This is the installation path of the Lisp interpreter.
 Example:
 Example:
     let g:slimv_impl = 'sbcl'
 
+                                                            *g:slimv_preferred*
+Name of the preferred lisp implementation. The autodetection mechanism tries to
+choose this one if possible, i.e. if installed and found in the path or in the
+standard installation directories.
+It's typical use is when there are multiple lisps present in the system and
+the autodetection chooses an undesired implementation.
+
+Valid choices are for lisp:
+    'sbcl', 'clisp', 'cmu', 'ecl', 'allegro', 'lispworks', 'clozure'
+For Scheme:
+    'mit'
+
+Example:
+    let g:slimv_preferred = 'clisp'
+This means that Slimv will use clisp even if both sbcl and clisp are installed
+and the autodetection would choose sbcl.
+
                                                             *g:slimv_swank_cmd*
                                                         *g:slimv_swank_clojure*
                                                          *g:slimv_swank_scheme*
-Slimv tries to autodetect your Python/Lisp/SWANK installation.
+Slimv tries to autodetect your Lisp/SWANK installation.
 If the location for the SWANK server is not identified by the script, or you
 want to use a different command for starting the SWANK server, then you may
 want to customize the g:slimv_swank_cmd (general) and g:slimv_swank_clojure
 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 unencrypted
 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.
+Actually there is a workaround for this: run Vim inside a GNU screen session.
+Slimv will autodetect this and modify the Swank command so that the Swank
+server is run inside a newly opened virtual terminal in screen.
 
                                                                  *g:swank_port*
 The SWANK server is connected to port 4005 by default. This can be changed
 Hyperspec or the Clojure API. If the command contains spaces then enclose the
 whole string in double quotes or escape the spaces with a backslash.
 This option is empty by default, which means that the command associated with
-the .html extension (on Windows) or returned by the Python webbrowser package
-(on Linux) is used to start the browser.
+the .html extension (on Windows) or xdg-open (on Linux) is used to start the
+browser. If xdg-open is not installed then the Python webbrowser package is
+used to identify the default browser on Linux.
 
                                                             *g:slimv_repl_name*
 Name of the REPL buffer. Default is 'REPL'. Space and some other special
 characters need to be escaped (e.g. 'Slimv\ Incpector', '\#INSPECT\#').
 Not all special characters are allowed, e.g. '*' does not work in Windows.
 
+                                                         *g:slimv_threads_name*
+Name of the Threads buffer. Default is 'THREADS'. Space and some other special
+characters need to be escaped (e.g. 'Slimv\ Threads', '\#THREADS\#').
+Not all special characters are allowed, e.g. '*' does not work in Windows.
+
                                                            *g:slimv_repl_split*
 Open the Lisp REPL buffer in a split window or in a separate buffer in Vim.
 The default is to use split window. If you prefer having REPL being in a hidden
 If nonzero then Slimv package/namespace handling is switched on. Please find
 details in the |slimv-package| section.
 
+                                                         *g:slimv_repl_max_len*
+Maximum number of lines for the REPL buffer. Only the last this number of lines
+are kept in the REPL buffer, all lines before that are erased, but some opening
+parens and/or double quotes may remain in order to maintain their balanced
+state. The default value for this option is 0, meaning that the number of lines
+is unlimited, i.e. no line is ever erased.
+
                                                           *g:slimv_repl_syntax*
 Enables syntax highlighting for the REPL buffer. Switched off by default for
 two reasons:
 |swank-describe|             Describe symbol in tooltip
 |swank-completions|          List of possible symbol completions
 |swank-inspect|              Inspector
+|swank-threads|              Threads
 |swank-trace|                Trace function
 |swank-profile|              Profiler
 |swank-xref|                 Cross Reference
 then Slimv exits the Inspector.
 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.
+
 
 If debugger is activated and the cursor is placed on a frame line in the
 Backtrace section, then the Inspect command inspects objects in the given
 
 
 -------------------------------------------------------------------------------
+THREADS                                                         *swank-threads*
+
+The Swank Threads are presented in a separate buffer.
+
+When the cursor is placed on a thread-line and <Backspace> or <Leader>k is
+pressed or the Kill-Thread function is selected then the given thread is killed.
+If multiple thread-lines are selected then all marked threads are killed.
+
+When the cursor is placed on a thread-line and <Leader>d is pressed or the
+Debug-Thread function is selected then the given thread is interrupted and the
+debugger is invoked.
+
+Pressing <Leader>r refreshes the thread list.
+
+Pressing <Leader>q exits the Threads buffer.
+
+-------------------------------------------------------------------------------
 TRACE                                                             *swank-trace*
 
 It is possible to tell the SWANK server to trace or untrace functions.
          :echo SlimvSwankCommand()         
      Also check the following Slimv variables in Vim, maybe they are not
      correctly autodetected and you need to override them in your .vimrc:
-         :echo g:slimv_python
          :echo g:slimv_lisp
          :echo g:slimv_swank_cmd   (or g:slimv_swank_clojure for Clojure)
 
 ===============================================================================
 CHANGE LOG                                                    *slimv-changelog*
 
+0.9.3  - Start Swank server in virtual terminal when running in GNU screen
+         on Linux (thanks to Oleg Terenchuk).
+       - Reuse a window for slimv also when there are three or more windows open.
+       - Don't go to end of REPL buffer if user moved the cursor away from EOF.
+       - Use xdg-open for default browser in Linux.
+       - Removed option g:slimv_python.
+       - Added option g:slimv_repl_max_len for limiting the number of lines in
+         the REPL buffer.
+       - Added option g:slimv_preferred to choose preferred lisp implementation.
+       - Query additional parts of big inspected object upon pressing Enter on
+         [--more--].
+       - Thread List is displayed and handled in a separate Threads buffer.
+       - Bugfix: window navigation problems between source/REPL/SLDB/etc.
+       - Bugfix: error messages when Swank server window is closed.
+       - Bugfix: return control to vim after starting browser defined by
+         g:slimv_browser_cmd.
+       - Bugfix: fixed indentation of arguments before &body argument.
+       - Bugfix: autocomplete for dotted package/namespace names.
+       - Bugfix: indentation of aif.
+
 0.9.2  - Added option g:swank_log to enable swank debug log.
        - Added options g:slimv_repl_name, g:slimv_sldb_name, g:slimv_inspect_name.
        - Added option g:slimv_indent_maxlines.
 
 - Vim register "s is used for all form selections, so its original content is
   destroyed.
-- Vim mark 's is used to mark the end of the REPL buffer, i.e. the beginning
-  of the "command line", also the for the location of the current frame in
-  the SLDB buffer.
 - Needs Vim version 7.0 or above, because of the intensive use of lists.
 - Needs the same Python version that Vim is compiled against
 - It is not possible to run separate Lisp and Clojure REPL in the same
   Slimv session.
-- Recent macvim (OS X) versions seem to have a Python 2.7 binding problem
+- Recent macvim (OS X) 64-bit versions seem to have a Python 2.7 binding problem
   causing segmentation faults when Slimv tries to connect to the Swank server.
-  One possible solution is to rebuild macvim with Python binding changed to 2.6.
+  One possible solution is to use the 32-bit version of macvim.
+  Another solution is to rebuild macvim with Python binding changed to 2.6.
 
 
 ===============================================================================
 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, Chris Cahoon, Mats Rauhala for additional
-notes and contributions.
+�mer Sinan Agacan, Tobias Pflug, Chris Cahoon, Mats Rauhala, Oleg Terenchuk
+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: :)

ftplugin/clojure/slimv-clojure.vim

 " slimv-clojure.vim:
 "               Clojure filetype plugin for Slimv
-" Version:      0.9.2
-" Last Change:  20 Oct 2011
+" Version:      0.9.3
+" Last Change:  06 Dec 2011
 " Maintainer:   Tamas Kovacs <kovisoft at gmail dot com>
 " License:      This file is placed in the public domain.
 "               No warranty, express or implied.
 
 " Try to autodetect Clojure executable
 " Returns list [Clojure executable, Clojure implementation]
-function! b:SlimvAutodetect()
+function! b:SlimvAutodetect( preferred )
     " Firts try the most basic setup: everything in the path
     if executable( 'lein' )
         return ['"lein repl"', 'clojure']
     return 'clojure'
 endfunction
 
+" Try to autodetect SWANK and build the command to load the SWANK server
+function! b:SlimvSwankLoader()
+    " First autodetect Leiningen and Cake
+    if executable( 'lein' )
+        return '"lein swank"'
+    elseif executable( 'cake' )
+        return '"cake swank"'
+    else
+        " Check if swank-clojure is bundled with Slimv
+        let swanks = split( globpath( &runtimepath, 'swank-clojure/swank/swank.clj'), '\n' )
+        if len( swanks ) == 0
+            return ''
+        endif
+        let sclj = substitute( swanks[0], '\', '/', "g" )
+        return g:slimv_lisp . ' -i "' . sclj . '" -e "(swank.swank/start-repl)" -r'
+    endif
+endfunction
+
 " Filetype specific initialization for the REPL buffer
 function! b:SlimvInitRepl()
     set filetype=clojure

ftplugin/lisp/slimv-lisp.vim

 " slimv-lisp.vim:
 "               Lisp filetype plugin for Slimv
-" Version:      0.9.2
-" Last Change:  20 Oct 2011
+" Version:      0.9.3
+" Last Change:  06 Dec 2011
 " Maintainer:   Tamas Kovacs <kovisoft at gmail dot com>
 " License:      This file is placed in the public domain.
 "               No warranty, express or implied.
 
 let g:slimv_lisp_loaded = 1
 
+" Descriptor array for various lisp implementations
+" The structure of an array element is:
+"     [ executable, implementation, platform, search path]
+" where:
+"     executable  - may contain wildcards but only if a search path is present
+"     platform    - 'w' (Windows) or 'l' (Linux = non-Windows), '' for all
+"     search path - commma separated list, may contain wildcard characters
+let s:lisp_desc = [
+\ [ 'sbcl',        'sbcl',      '',  '' ],
+\ [ 'clisp',       'clisp',     '',  '' ],
+\ [ 'gcl',         'clisp',     '',  '' ],
+\ [ 'cmucl',       'cmu',       '',  '' ],
+\ [ 'ecl',         'ecl',       '',  '' ],
+\ [ 'acl',         'allegro',   '',  '' ],
+\ [ 'mlisp',       'allegro',   '',  '' ],
+\ [ 'mlisp8',      'allegro',   '',  '' ],
+\ [ 'alisp',       'allegro',   '',  '' ],
+\ [ 'alisp8',      'allegro',   '',  '' ],
+\ [ 'lwl',         'lispworks', '',  '' ],
+\ [ 'wx86cl',      'clozure',   'w', '' ],
+\ [ 'lx86cl',      'clozure',   'l', '' ],
+\ [ '*lisp.exe',   'clisp',     'w',
+\   'c:/*lisp*,c:/*lisp*/*,c:/*lisp*/bin/*,c:/Program Files/*lisp*,c:/Program Files/*lisp*/*,c:/Program Files/*lisp*/bin/*' ],
+\ [ 'gcl.exe',     'clisp',     'w', 'c:/gcl*,c:/Program Files/gcl*' ],
+\ [ 'cmucl.exe',   'cmu',       'w', 'c:/cmucl*,c:/Program Files/cmucl*' ],
+\ [ '*lisp*.exe',  'allegro',   'w', 'c:/acl*,c:/Program Files/acl*,c:/Program Files/*lisp*/bin/acl*' ],
+\ [ 'ecl.exe',     'ecl',       'w', 'c:/ecl*,c:/Program Files/ecl*' ],
+\ [ 'wx86cl.exe',  'clozure',   'w', 'c:/ccl*,c:/Program Files/ccl*,c:/Program Files/*lisp*/bin/ccl*' ],
+\ [ 'sbcl.exe',    'sbcl',      'w', 'c:/sbcl*,c:/Program Files/sbcl*,c:/Program Files/*lisp*/bin/sbcl*'] ]
+
 " Try to autodetect Lisp executable
 " Returns list [Lisp executable, Lisp implementation]
-function! b:SlimvAutodetect()
-    " Check the easy cases
-    if executable( 'sbcl' )
-        " Steel Bank Common Lisp
-        return ['sbcl', 'sbcl']
-    endif
-    if executable( 'clisp' )
-        " Common Lisp
-        return ['clisp', 'clisp']
-    endif
-    if executable( 'gcl' )
-        " GNU Common Lisp
-        return ['gcl', 'clisp']
-    endif
-    if executable( 'cmucl' )
-        " Carnegie Mellon University Common Lisp
-        return ['cmucl', 'cmu']
-    endif
-    if executable( 'ecl' )
-        " Embeddable Common Lisp
-        return ['ecl', 'ecl']
-    endif
-    if executable( 'acl' )
-        " Allegro Common Lisp
-        return ['acl', 'allegro']
-    endif
-    if executable( 'mlisp' )
-        " Allegro Common Lisp
-        return ['mlisp', 'allegro']
-    endif
-    if executable( 'mlisp8' )
-        " Allegro Common Lisp
-        return ['mlisp8', 'allegro']
-    endif
-    if executable( 'alisp' )
-        " Allegro Common Lisp
-        return ['alisp', 'allegro']
-    endif
-    if executable( 'alisp8' )
-        " Allegro Common Lisp
-        return ['alisp8', 'allegro']
-    endif
-    if executable( 'lwl' )
-        " LispWorks
-        return ['lwl', 'lispworks']
-    endif
-    if g:slimv_windows && executable( 'wx86cl' )
-        " Clozure CL
-        return ['wx86cl', 'clozure']
-    endif
-    if !g:slimv_windows && executable( 'lx86cl' )
-        " Clozure CL
-        return ['lx86cl', 'clozure']
-    endif
-
-    if g:slimv_windows
-        " Try to find Lisp on the standard installation places
-        let lisps = split( globpath( 'c:/*lisp*,c:/*lisp*/*,c:/*lisp*/bin/*,c:/Program Files/*lisp*,c:/Program Files/*lisp*/*,c:/Program Files/*lisp*/bin/*', '*lisp.exe' ), '\n' )
-        if len( lisps ) > 0
-            return [lisps[0], 'clisp']
-        endif
-        let lisps = split( globpath( 'c:/gcl*,c:/Program Files/gcl*', 'gcl.exe' ), '\n' )
-        if len( lisps ) > 0
-            return [lisps[0], 'clisp']
-        endif
-        let lisps = split( globpath( 'c:/cmucl*,c:/Program Files/cmucl*', 'cmucl.exe' ), '\n' )
-        if len( lisps ) > 0
-            return [lisps[0], 'cmu']
-        endif
-        let lisps = split( globpath( 'c:/sbcl*,c:/Program Files/sbcl*,c:/Program Files/*lisp*/bin/sbcl*', 'sbcl.exe' ), '\n' )
-        if len( lisps ) > 0
-            return [lisps[0], 'sbcl']
-        endif
-        let lisps = split( globpath( 'c:/acl*,c:/Program Files/acl*,c:/Program Files/*lisp*/bin/acl*', '*lisp*.exe' ), '\n' )
-        if len( lisps ) > 0
-            return [lisps[0], 'allegro']
-        endif
-        let lisps = split( globpath( 'c:/ecl*,c:/Program Files/ecl*', 'ecl.exe' ), '\n' )
-        if len( lisps ) > 0
-            return [lisps[0], 'ecl']
-        endif
-        let lisps = split( globpath( 'c:/ccl*,c:/Program Files/ccl*,c:/Program Files/*lisp*/bin/ccl*', 'wx86cl.exe' ), '\n' )
-        if len( lisps ) > 0
-            return [lisps[0], 'clozure']
+function! b:SlimvAutodetect( preferred )
+    for lisp in s:lisp_desc
+        if     lisp[2] == 'w' && !g:slimv_windows
+            " Valid only on Windows
+        elseif lisp[2] == 'l' &&  g:slimv_windows
+            " Valid only on Linux
+        elseif a:preferred != '' && a:preferred != lisp[1]
+            " Not the preferred implementation
+        elseif lisp[3] != ''
+            " A search path is given
+            let lisps = split( globpath( lisp[3], lisp[0] ), '\n' )
+            if len( lisps ) > 0
+                return [lisps[0], lisp[1]]
+            endif
+        else
+            " Single executable is given without path
+            if executable( lisp[0] )
+                return lisp[0:1]
+            endif
         endif
-    endif
-
+    endfor
     return ['', '']
 endfunction
 
         return tolower( g:slimv_impl )
     endif
 
-    if exists( 'g:slimv_lisp' ) && match( tolower( g:slimv_lisp ), 'sbcl' ) >= 0
+    let lisp = tolower( g:slimv_lisp )
+    if match( lisp, 'sbcl' ) >= 0
         return 'sbcl'
     endif
+    if match( lisp, 'cmu' ) >= 0
+        return 'cmu'
+    endif
+    if match( lisp, 'acl' ) >= 0 || match( lisp, 'alisp' ) >= 0 || match( lisp, 'mlisp' ) >= 0
+        return 'allegro'
+    endif
+    if match( lisp, 'ecl' ) >= 0
+        return 'ecl'
+    endif
+    if match( lisp, 'x86cl' ) >= 0
+        return 'clozure'
+    endif
+    if match( lisp, 'lwl' ) >= 0
+        return 'lispworks'
+    endif
 
     return 'clisp'
 endfunction
 
+" Try to autodetect SWANK and build the command to load the SWANK server
+function! b:SlimvSwankLoader()
+    " First check if SWANK is bundled with Slimv
+    let swanks = split( globpath( &runtimepath, 'slime/start-swank.lisp'), '\n' )
+    if len( swanks ) == 0
+        " Try to find SWANK in the standard SLIME installation locations
+        if g:slimv_windows || g:slimv_cygwin
+            let swanks = split( globpath( 'c:/slime/,c:/*lisp*/slime/,c:/*lisp*/site/lisp/slime/,c:/Program Files/*lisp*/site/lisp/slime/', 'start-swank.lisp' ), '\n' )
+        else
+            let swanks = split( globpath( '/usr/share/common-lisp/source/slime/', 'start-swank.lisp' ), '\n' )
+        endif
+    endif
+    if len( swanks ) == 0
+        return ''
+    endif
+
+    " Build proper SWANK loader command for the Lisp implementation used
+    if g:slimv_impl == 'sbcl'
+        return '"' . g:slimv_lisp . '" --load "' . swanks[0] . '"'
+    elseif g:slimv_impl == 'clisp'
+        return '"' . g:slimv_lisp . '" -i "' . swanks[0] . '"'
+    elseif g:slimv_impl == 'allegro'
+        return '"' . g:slimv_lisp . '" -L "' . swanks[0] . '"'
+    elseif g:slimv_impl == 'cmu'
+        return '"' . g:slimv_lisp . '" -load "' . swanks[0] . '"'
+    else
+        return '"' . g:slimv_lisp . '" -l "' . swanks[0] . '"'
+    endif
+endfunction
+
 " Filetype specific initialization for the REPL buffer
 function! b:SlimvInitRepl()
     set filetype=lisp

ftplugin/scheme/slimv-scheme.vim

 " slimv-scheme.vim:
 "               Scheme filetype plugin for Slimv
-" Version:      0.9.2
-" Last Change:  20 Oct 2011
+" Version:      0.9.3
+" Last Change:  06 Dec 2011
 " Maintainer:   Tamas Kovacs <kovisoft at gmail dot com>
 " License:      This file is placed in the public domain.
 "               No warranty, express or implied.
 
 " Try to autodetect Scheme executable
 " Returns list [Scheme executable, Scheme implementation]
-function! b:SlimvAutodetect()
+function! b:SlimvAutodetect( preferred )
     " Currently only MIT Scheme on Linux
     if executable( 'scheme' )
         " MIT Scheme
     return 'mit'
 endfunction
 
+" Try to autodetect SWANK and build the command to load the SWANK server
+function! b:SlimvSwankLoader()
+    let swanks = split( globpath( &runtimepath, 'slime/contrib/swank-mit-scheme.scm'), '\n' )
+    if len( swanks ) == 0
+        return ''
+    endif
+    if g:slimv_impl == 'mit'
+        return '"' . g:slimv_lisp . '" --load "' . swanks[0] . '"'
+    endif
+    return ''
+endfunction
+
 " Filetype specific initialization for the REPL buffer
 function! b:SlimvInitRepl()
     set filetype=scheme

ftplugin/slimv.vim

 " slimv.vim:    The Superior Lisp Interaction Mode for VIM
-" Version:      0.9.2
-" Last Change:  25 Oct 2011
+" Version:      0.9.3
+" Last Change:  22 Dec 2011
 " Maintainer:   Tamas Kovacs <kovisoft at gmail dot com>
 " License:      This file is placed in the public domain.
 "               No warranty, express or implied.
 "  Functions used by global variable definitions
 " =====================================================================
 
-" Try to autodetect Python executable
-function! SlimvAutodetectPython()
-    if !g:slimv_cygwin && executable( 'python' )
-        return 'python'
-    endif
-
-    if g:slimv_windows || g:slimv_cygwin
-        " Try to find Python on the standard installation places
-        " For Cygwin we need to use the Windows Python instead of the Cygwin Python
-        let pythons = split( globpath( 'c:/python*,c:/Program Files/python*', 'python.exe' ), '\n' )
-        if len( pythons ) == 0
-            " Go deeper in subdirectories
-            let pythons = split( globpath( 'c:/python*/**,c:/Program Files/python*/**', 'python.exe' ), '\n' )
-            if len( pythons ) == 0
-                return ''
-            endif
-        endif
-        let pycmd = pythons[0]
-        if match( pycmd, ' ' ) >= 0
-            " Convert Python command to short 8.3 format if path contains spaces
-            let pycmd = fnamemodify( pycmd, ':8' )
-        endif
-        return pycmd
-    else
-        return ''
-    endif
-endfunction
-
 " Convert Cygwin path to Windows path, if needed
 function! s:Cygpath( path )
     let path = a:path
         let g:slimv_lisp = input( 'Enter Lisp path (or fill g:slimv_lisp in your vimrc): ', '', 'file' )
     endif
 
-    let cmd = ''
-    if SlimvGetFiletype() == 'clojure'
-        " 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' )
-            if len( swanks ) == 0
-                return ''
-            endif
-            let sclj = substitute( swanks[0], '\', '/', "g" )
-            let cmd = g:slimv_lisp . ' -i "' . sclj . '" -e "(swank.swank/start-repl)" -r'
-        endif
-    elseif SlimvGetFiletype() == 'scheme'
-        let swanks = split( globpath( &runtimepath, 'slime/contrib/swank-mit-scheme.scm'), '\n' )
-        if len( swanks ) == 0
-            return ''
-        endif
-        if b:SlimvImplementation() == 'mit'
-            let cmd = '"' . g:slimv_lisp . '" --load "' . swanks[0] . '"'
-        endif
-    else
-        " First check if SWANK is bundled with Slimv
-        let swanks = split( globpath( &runtimepath, 'slime/start-swank.lisp'), '\n' )
-        if len( swanks ) == 0
-            " Try to find SWANK in the standard SLIME installation locations
-            if g:slimv_windows || g:slimv_cygwin
-                let swanks = split( globpath( 'c:/slime/,c:/*lisp*/slime/,c:/*lisp*/site/lisp/slime/,c:/Program Files/*lisp*/site/lisp/slime/', 'start-swank.lisp' ), '\n' )
-            else
-                let swanks = split( globpath( '/usr/share/common-lisp/source/slime/', 'start-swank.lisp' ), '\n' )
-            endif
-        endif
-        if len( swanks ) == 0
-            return ''
-        endif
-
-        " Build proper SWANK start command for the Lisp implementation used
-        if b:SlimvImplementation() == 'sbcl'
-            let cmd = '"' . g:slimv_lisp . '" --load "' . swanks[0] . '"'
-        elseif b:SlimvImplementation() == 'clisp'
-            let cmd = '"' . g:slimv_lisp . '" -i "' . swanks[0] . '"'
-        elseif b:SlimvImplementation() == 'allegro'
-            let cmd = '"' . g:slimv_lisp . '" -L "' . swanks[0] . '"'
-        elseif b:SlimvImplementation() == 'cmu'
-            let cmd = '"' . g:slimv_lisp . '" -load "' . swanks[0] . '"'
-        else
-            let cmd = '"' . g:slimv_lisp . '" -l "' . swanks[0] . '"'
-        endif
-    endif
+    let cmd = b:SlimvSwankLoader()
     if cmd != ''
         if g:slimv_windows || g:slimv_cygwin
             return '!start /MIN ' . cmd
         elseif g:slimv_osx
             return '!osascript -e "tell application \"Terminal\" to do script \"' . cmd . '\""'
+        elseif $STY != ''
+	    " GNU screen under Linux
+	    return '! screen -X eval "title slimv" "screen ' . cmd . '" "select slimv"'
         else
+	    " Must be Linux
             return '! xterm -iconic -e ' . cmd . ' &'
         endif
     endif
     let g:swank_port = 4005
 endif
 
-" Find Python (if not given in vimrc)
-if !exists( 'g:slimv_python' )
-    let g:slimv_python = SlimvAutodetectPython()
-endif
-
 " Find Lisp (if not given in vimrc)
 if !exists( 'g:slimv_lisp' )
-    let lisp = b:SlimvAutodetect()
+    let lisp = ['', '']
+    if exists( 'g:slimv_preferred' )
+        let lisp = b:SlimvAutodetect( tolower(g:slimv_preferred) )
+    endif
+    if lisp[0] == ''
+        let lisp = b:SlimvAutodetect( '' )
+    endif
     let g:slimv_lisp = lisp[0]
     if !exists( 'g:slimv_impl' )
         let g:slimv_impl = lisp[1]
     let g:slimv_inspect_name = 'INSPECT'
 endif
 
+" THREADS buffer name
+if !exists( 'g:slimv_threads_name' )
+    let g:slimv_threads_name = 'THREADS'
+endif
+
 " Shall we open REPL buffer in split window?
 if !exists( 'g:slimv_repl_split' )
     let g:slimv_repl_split = 1
     let g:slimv_indent_maxlines = 20
 endif
 
+" Maximum length of the REPL buffer
+if !exists( 'g:slimv_repl_max_len' )
+    let g:slimv_repl_max_len = 0
+endif
 
 " =====================================================================
 "  Template definitions
 "  Other non-global script variables
 " =====================================================================
 
-let s:prompt = ''                                         " Lisp prompt in the last line
 let s:indent = ''                                         " Most recent indentation info
 let s:last_update = 0                                     " The last update time for the REPL buffer
 let s:save_updatetime = &updatetime                       " The original value for 'updatetime'
 " Position the cursor at the end of the REPL buffer
 " Optionally mark this position in Vim mark 's'
 function! SlimvEndOfReplBuffer()
-    normal! G$
+    if line( '.' ) >= b:repl_prompt_line
+        " Go to the end of file only if the user did not move up from here
+        normal! G$
+    endif
 endfunction
 
 " Remember the end of the REPL buffer: user may enter commands here
 function! SlimvMarkBufferEnd()
     setlocal nomodified
     call SlimvEndOfReplBuffer()
-    call setpos( "'s", [0, line('$'), col('$'), 0] )
-    let s:prompt = getline( "'s" )
+    let b:repl_prompt_line = line( '$' )
+    let b:repl_prompt_col = len( getline('$') ) + 1
+    let b:repl_prompt = getline( b:repl_prompt_line )
 endfunction
 
 " Save caller buffer identification
 
 " Stop updating the REPL buffer and switch back to caller
 function! SlimvEndUpdateRepl()
+    " Keep only the last g:slimv_repl_max_len lines
+    let lastline = line('$')
+    let prompt_offset = lastline - b:repl_prompt_line
+    if g:slimv_repl_max_len > 0 && lastline > g:slimv_repl_max_len
+        let start = ''
+        let ending = s:CloseForm( getline( 1, lastline - g:slimv_repl_max_len ) )
+        if match( ending, ')\|\]\|}\|"' ) >= 0
+            " Reverse the ending and replace matched characters with their pairs
+            let start = join( reverse( split( ending, '.\zs' ) ), '' )
+            let start = substitute( start, ')', '(', 'g' )
+            let start = substitute( start, ']', '[', 'g' )
+            let start = substitute( start, '}', '{', 'g' )
+        endif
+
+        " Delete extra lines
+        execute "python vim.current.buffer[0:" . (lastline - g:slimv_repl_max_len) . "] = []"
+
+        " Re-balance the beginning of the buffer
+        if start != ''
+            call append( 0, start . " .... ; output shortened" )
+        endif
+        let b:repl_prompt_line = line( '$' ) - prompt_offset
+    endif
+
+    " Mark current prompt position
     call SlimvMarkBufferEnd()
     let repl_buf = bufnr( g:slimv_repl_name )
     let repl_win = bufwinnr( repl_buf )
         " 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
+        if bufname('%') != g:slimv_sldb_name && bufname('%') != g:slimv_inspect_name && bufname('%') != g:slimv_threads_name
             call feedkeys("\<insert>\<insert>")
         endif
     else
 
 " View the given file in a top/bottom/left/right split window
 function! s:SplitView( filename )
-    if winnr('$') == 2
-        " We have exactly two windows
-         if bufnr("%") == s:current_buf && winnr() == s:current_win
+    if winnr('$') >= 2
+        " We have already at least two windows
+        if bufnr("%") == s:current_buf && winnr() == s:current_win
             " Keep the current window on screen, use the other window for the new buffer
-            execute "wincmd w"
-         endif
+            execute "wincmd p"
+        endif
         execute "silent view! " . a:filename
     else
+        " No windows yet, need to split
         if g:slimv_repl_split == 1
             execute "silent topleft sview! " . a:filename
         elseif g:slimv_repl_split == 2
         set syntax=
     endif
 
+    " Prompt and its line and column number in the REPL buffer
+    if !exists( 'b:repl_prompt' )
+        let b:repl_prompt = ''
+        let b:repl_prompt_line = 1
+        let b:repl_prompt_col = 1
+    endif
+
     " Add keybindings valid only for the REPL buffer
     inoremap <buffer> <silent>        <CR>   <C-R>=pumvisible() ? "\<lt>CR>" : "\<lt>End>\<lt>C-O>:call SlimvSendCommand(0)\<lt>CR>"<CR>
     inoremap <buffer> <silent>        <C-CR> <End><C-O>:call SlimvSendCommand(1)<CR>
 " Open a new Inspect buffer
 function SlimvOpenInspectBuffer()
     call SlimvOpenBuffer( g:slimv_inspect_name )
+    let b:range_start = 0
+    let b:range_end   = 0
 
     " Add keybindings valid only for the Inspect buffer
     noremap  <buffer> <silent>        <CR>   :call SlimvHandleEnterInspect()<CR>
     noremap  <buffer> <silent> <Backspace>   :call SlimvSendSilent(['[-1]'])<CR>
     execute 'noremap <buffer> <silent> ' . g:slimv_leader.'q      :call SlimvQuitInspect()<CR>'
+
+    syn match Type /^\[\d\+\]/
+    syn match Type /^\[<<\]/
+    syn match Type /^\[--more--\]$/
+endfunction
+
+" Open a new Threads buffer
+function SlimvOpenThreadsBuffer()
+    call SlimvOpenBuffer( g:slimv_threads_name )
+
+    " Add keybindings valid only for the Threads buffer
+    "noremap  <buffer> <silent>        <CR>   :call SlimvHandleEnterThreads()<CR>
+    noremap  <buffer> <silent> <Backspace>                        :call SlimvKillThread()<CR>
+    execute 'noremap <buffer> <silent> ' . g:slimv_leader.'r      :call SlimvListThreads()<CR>'
+    execute 'noremap <buffer> <silent> ' . g:slimv_leader.'d      :call SlimvDebugThread()<CR>'
+    execute 'noremap <buffer> <silent> ' . g:slimv_leader.'k      :call SlimvKillThread()<CR>'
+    execute 'noremap <buffer> <silent> ' . g:slimv_leader.'q      :call SlimvQuitThreads()<CR>'
 endfunction
 
 " Open a new SLDB buffer
     b #
 endfunction
 
+" Quit Threads
+function SlimvQuitThreads()
+    " Clear the contents of the Threads buffer
+    setlocal noreadonly
+    silent! %d
+    call SlimvEndUpdate()
+    b #
+endfunction
+
 " Quit Sldb
 function SlimvQuitSldb()
     " Clear the contents of the Sldb buffer
 " Set command line after the prompt
 function! SlimvSetCommandLine( cmd )
     let line = getline( "." )
-    if line( "." ) == line( "'s" )
-        " The prompt is in the line marked with 's
-        let promptlen = len( s:prompt )
+    if line( "." ) == b:repl_prompt_line
+        " The prompt is in the line marked by b:repl_prompt_line
+        let promptlen = len( b:repl_prompt )
     else
         let promptlen = 0
     endif
     " Check if the current form started in the previous nonblank line
     if l == pnum
         " Found opening paren in the previous line, let's find out the function name
-        let func = matchstr( getline(l), '\<\k*\>', c )
+        let line = getline(l)
+        let func = matchstr( line, '\<\k*\>', c )
         " If it's a keyword, keep the indentation straight
         if strpart(func, 0, 1) == ':'
             return c
                 return c + 1
             endif
         else
-            if match( func, 'defgeneric$' ) >= 0
+            if match( func, 'defgeneric$' ) >= 0 || match( func, 'aif$' ) >= 0
                 return c + 1
             endif
         endif
         " Remove package specification
         let func = substitute(func, '^.*:', '', '')
         if func != '' && s:swank_connected
+            " Look how many arguments are on the same line
+            let args = strpart( line, c )
+            " Contract strings, remove comments
+            let args = substitute( args, '".\{-}[^\\]"', '""', 'g' )
+            let args = substitute( args, ';.*$', '', 'g' )
+            " Contract subforms by replacing them with a single character
+            let args0 = ''
+            while args != args0
+                let args0 = args
+                let args = substitute( args, '([^()]*)',     'x', 'g' )
+                let args = substitute( args, '\[[^\[\]]*\]', 'x', 'g' )
+                let args = substitute( args, '{[^{}]*}',     'x', 'g' )
+            endwhile
+            " Remove leftover parens and other special characters
+            let args = substitute( args, "[()\\[\\]{}#'`,]", '', 'g' )
+            let args_here = len( split( args ) ) - 1
+            " Get swank indent info
             let s:indent = ''
             silent execute 'python get_indent_info("' . func . '")'
-            if s:indent >= '0' && s:indent <= '9'
-                " Function has &body argument, so indent by 2 spaces from the opening '('
+            if s:indent == args_here
+                " The next one is an &body argument, so indent by 2 spaces from the opening '('
                 return c + 1
             endif
         endif
 " Arguments: close = add missing closing parens
 function! SlimvSendCommand( close )
     call SlimvRefreshModeOn()
-    let lastline = line( "'s" )
-    let lastcol  =  col( "'s" )
+    let lastline = b:repl_prompt_line
+    let lastcol  = b:repl_prompt_col
     if lastline > 0
         if line( "." ) >= lastline
             " Trim the prompt from the beginning of the command line
             " The user might have overwritten some parts of the prompt
             let cmdline = getline( lastline )
             let c = 0
-            while c < lastcol - 1 && cmdline[c] == s:prompt[c]
+            while c < lastcol - 1 && cmdline[c] == b:repl_prompt[c]
                 let c = c + 1
             endwhile
             let cmd = [ strpart( getline( lastline ), c ) ]
 
 " Handle insert mode 'Backspace' keypress in the REPL buffer
 function! SlimvHandleBS()
-    if line( "." ) == line( "'s" ) && col( "." ) <= col( "'s" )
+    if line( "." ) == b:repl_prompt_line && col( "." ) <= b:repl_prompt_col
         " No BS allowed before the previous EOF mark
         return ""
     else
 
 " Handle insert mode 'Up' keypress in the REPL buffer
 function! SlimvHandleUp()
-    if line( "." ) >= line( "'s" )
+    if line( "." ) >= b:repl_prompt_line
         if exists( 'g:slimv_cmdhistory' ) && g:slimv_cmdhistorypos == len( g:slimv_cmdhistory )
             call SlimvMarkBufferEnd()
             startinsert!
 
 " Handle insert mode 'Down' keypress in the REPL buffer
 function! SlimvHandleDown()
-    if line( "." ) >= line( "'s" )
+    if line( "." ) >= b:repl_prompt_line
         call s:NextCommand()
     else
         normal! gj
         if len(mlist)
             if g:slimv_repl_split
                 " Switch back to other window
-                execute "wincmd w"
+                execute "wincmd p"
             endif
             " Jump to the file at the specified position
             if mlist[2] == 'line'
                 " Display item-th frame
                 call SlimvMakeFold()
                 silent execute 'python swank_frame_locals("' . item . '")'
-                if b:SlimvImplementation() != 'clisp'
+                if g:slimv_impl != 'clisp'
                     " These are not implemented for CLISP
                     silent execute 'python swank_frame_source_loc("' . item . '")'
                     silent execute 'python swank_frame_call("' . item . '")'
     endif
 
     if line[0] == '['
-        if line[0:3] == '[<<]'
+        if line =~ '^[--more--\]$'
+            " More data follows, fetch next part
+            call SlimvCommand( 'python swank_inspector_range()' )
+            call SlimvRefreshReplBuffer()
+            return
+        elseif line[0:3] == '[<<]'
             " Pop back up in the inspector
             let item = '-1'
         else
 " Go to command line and recall previous command from command history
 function! SlimvPreviousCommand()
     call SlimvEndOfReplBuffer()
-    if line( "." ) >= line( "'s" )
+    if line( "." ) >= b:repl_prompt_line
         call s:PreviousCommand()
     endif
 endfunction
 " Go to command line and recall next command from command history
 function! SlimvNextCommand()
     call SlimvEndOfReplBuffer()
-    if line( "." ) >= line( "'s" )
+    if line( "." ) >= b:repl_prompt_line
         call s:NextCommand()
     endif
 endfunction
         if a:firstline == a:lastline
             let line = getline('.')
             let item = matchstr( line, '\d\+' )
-            let item = input( 'Thread to kill: ', item )
+            if bufname('%') != g:slimv_threads_name
+                " We are not in the Threads buffer, not sure which thread to kill
+                let item = input( 'Thread to kill: ', item )
+            endif
             if item != ''
                 call SlimvCommand( 'python swank_kill_thread(' . item . ')' )
                 call SlimvRefreshReplBuffer()
             endif
+            echomsg 'Thread ' . item . ' is killed.'
         else
             for line in getline(a:firstline, a:lastline)
                 let item = matchstr( line, '\d\+' )
             endfor
             call SlimvRefreshReplBuffer()
         endif
+        call SlimvListThreads()
     endif
 endfunction
 
         endif
         if exists( "g:slimv_browser_cmd" )
             " We have an given command to start the browser
-            silent execute '! ' . g:slimv_browser_cmd . ' ' . page
+            silent execute '! ' . g:slimv_browser_cmd . ' ' . page . ' &'
         else
             if g:slimv_windows
                 " Run the program associated with the .html extension
                 silent execute '! start ' . page
             else
                 " On Linux it's not easy to determine the default browser
-                " Ask help from Python webbrowser package
-                if g:slimv_python == ''
-                    let g:slimv_python = input( 'Enter Python path (or fill g:slimv_python in your vimrc): ', '', 'file' )
-                endif
-                if g:slimv_python == ''
-                    return
-                endif
-                let pycmd = "import webbrowser; webbrowser.open('" . page . "')"
-                silent execute '! ' . g:slimv_python . ' -c "' . pycmd . '"'
+		if executable( 'xdg-open' )
+                    silent execute '! xdg-open ' . page . ' &'
+	        else
+                    " xdg-open not installed, ask help from Python webbrowser package
+                    let pycmd = "import webbrowser; webbrowser.open('" . page . "')"
+                    silent execute '! python -c "' . pycmd . '"'
+		endif
             endif
         endif
         " This is needed especially when using text browsers
         " Locate the start of the symbol name
         call s:SetKeyword()
         let upto = strpart( getline( '.' ), 0, col( '.' ) - 1)
-        let p = match(upto, '\k\+$')
+        let p = match(upto, '\(\k\|\.\)\+$')
         return p 
     else
         return SlimvComplete( a:base )

ftplugin/swank.py

 #
 # SWANK client for Slimv
 # swank.py:     SWANK client code for slimv.vim plugin
-# Version:      0.9.2
-# Last Change:  26 Oct 2011
+# Version:      0.9.3
+# Last Change:  21 Dec 2011
 # Maintainer:   Tamas Kovacs <kovisoft at gmail dot com>
 # License:      This file is placed in the public domain.
 #               No warranty, express or implied.
 actions         = dict()        # Swank actions (like ':write-string'), by message id
 indent_info     = dict()        # Data of :indentation-update
 frame_locals    = dict()        # Map frame variable names to their index
+inspect_content = []            # Partial content of the last Inspect command
 
 
 ###############################################################################
                 rec = rec + data
     rec = ''
 
-def swank_parse_inspect(struct):
+def swank_parse_inspect_content(pcont):
     """
-    Parse the swank inspector output
+    Parse the swank inspector content
     """
-    vim.command('call SlimvOpenInspectBuffer()')
+    global inspect_content
+
+    cur_line = vim.eval('line(".")')
     buf = vim.current.buffer
-    buf[:] = ['Inspecting ' + parse_plist(struct, ':title'), '--------------------', '']
-    pcont = parse_plist(struct, ':content')
-    cont = pcont[0]
+    # First 3 lines are filled in swank_parse_inspect()
+    buf[3:] = []
+    if type(pcont[0]) == list:
+        inspect_content = inspect_content + pcont[0]  # Append to the previous content
+    istate = pcont[1]
+    start  = pcont[2]
+    end    = pcont[3]
     lst = []
     linestart = 0
-    for el in cont:
+    for el in inspect_content:
         logprint(str(el))
         if type(el) == list:
             if el[0] == ':action':
             lst.append(text)
             if text == "\n":
                 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 lst[linestart][0] == '[':
+            lst.append("\n[--more--]")
+        else:
+            lst[linestart:] = "[--more--]"
+    buf = vim.current.buffer
     buf.append("".join(lst).split("\n"))
     buf.append(['', '[<<]'])
+    vim.command('normal! ' + cur_line + 'G')
     vim.command('call SlimvEndUpdate()')
 
+def swank_parse_inspect(struct):
+    """
+    Parse the swank inspector output
+    """
+    global inspect_content
+
+    vim.command('call SlimvOpenInspectBuffer()')
+    buf = vim.current.buffer
+    buf[:] = ['Inspecting ' + parse_plist(struct, ':title'), '--------------------', '']
+    pcont = parse_plist(struct, ':content')
+    inspect_content = []
+    swank_parse_inspect_content(pcont)
+
 def swank_parse_debug(struct):
     """
     Parse the SLDB output
     return buf
 
 def swank_parse_list_threads(tl):
-    buf = ''
+    vim.command('call SlimvOpenThreadsBuffer()')
+    buf = vim.current.buffer
+    buf[:] = ['Idx  ID    Status                 Name                   Priority', \
+              '---- ----  --------------------   --------------------   ---------']
     lst = tl[1]
     headers = lst.pop(0)
     logprint(str(lst))
     idx = 0
     for t in lst:
-        buf = buf + "\n%3d. ID%3d: %-22s %s" % (idx, int(t[0]), unquote(t[2]), unquote(t[1]))
+        priority = ''
+        if len(t) > 3:
+            priority = unquote(t[3])
+        buf.append(["%3d:  %3d  %-22s %-22s %s" % (idx, int(t[0]), unquote(t[2]), unquote(t[1]), priority)])
         idx = idx + 1
-    return buf
+    vim.command('call SlimvEndUpdate()')
 
 def swank_parse_frame_call(struct, action):
     """
                         logprint('params: ' + str(params))
                         if type(params) == str:
                             element = params.lower()
-                            to_ignore = [':frame-call', ':quit-inspector']
+                            to_ignore = [':frame-call', ':quit-inspector', ':kill-thread', ':debug-thread']
                             to_nodisp = [':describe-symbol']
                             to_prompt = [':undefine-function', ':swank-macroexpand-1', ':swank-macroexpand-all', ':disassemble-form', \
                                          ':load-file', ':toggle-profile-fdefinition', ':profile-by-substring', ':swank-toggle-trace', 'sldb-break']
                                     retval = retval + new_line(retval) + prompt + '> '
 
                         elif type(params) == list and params:
-                            if type(params[0]) == list: 
-                                params = params[0]
                             element = ''
                             if type(params[0]) == str: 
                                 element = params[0].lower()
                                 retval = retval + new_line(retval) + swank_parse_compile(params) + prompt + '> '
                             else:
                                 if action.name == ':simple-completions':
-                                    if type(params) == list and type(params[0]) == str and params[0] != 'nil':
-                                        compl = "\n".join(params)
+                                    if type(params[0]) == list and type(params[0][0]) == str and params[0][0] != 'nil':
+                                        compl = "\n".join(params[0])
                                         retval = retval + compl.replace('"', '')
                                 elif action.name == ':fuzzy-completions':
-                                    if type(params) == list and type(params[0]) == list:
-                                        compl = "\n".join(map(lambda x: x[0], params))
+                                    if type(params[0]) == list and type(params[0][0]) == list:
+                                        compl = "\n".join(map(lambda x: x[0], params[0]))
                                         retval = retval + compl.replace('"', '')
                                 elif action.name == ':list-threads':
-                                    retval = retval + swank_parse_list_threads(r[1])
-                                    retval = retval + new_line(retval) + prompt + '> '
+                                    swank_parse_list_threads(r[1])
                                 elif action.name == ':xref':
                                     retval = retval + '\n' + swank_parse_xref(r[1][1])
                                     retval = retval + new_line(retval) + prompt + '> '
                                 elif action.name == ':frame-source-location':
                                     swank_parse_frame_source(params, action)
                                 elif action.name == ':frame-locals-and-catch-tags':
-                                    swank_parse_locals(params, action)
+                                    swank_parse_locals(params[0], action)
                                 elif action.name == ':profiled-functions':
                                     retval = retval + '\n' + 'Profiled functions:\n'
                                     for f in params:
                                         retval = retval + '  ' + f + '\n'
                                     retval = retval + prompt + '> '
+                                elif action.name == ':inspector-range':
+                                    swank_parse_inspect_content(params)
                                 if action:
                                     action.result = retval
 
 
 def swank_inspect(symbol):
     cmd = '(swank:init-inspector "' + symbol + '")'
-    swank_rex(':init-inspector', cmd, get_package(), 't')
+    swank_rex(':init-inspector', cmd, get_swank_package(), 't')
 
 def swank_inspect_nth_part(n):
     cmd = '(swank:inspect-nth-part ' + str(n) + ')'
-    swank_rex(':inspect-nth-part', cmd, 'nil', 't', str(n))
+    swank_rex(':inspect-nth-part', cmd, get_swank_package(), 't', str(n))
 
 def swank_inspector_nth_action(n):
     cmd = '(swank:inspector-call-nth-action ' + str(n) + ')'
         cmd = '(swank:inspect-in-frame "' + symbol + '" ' + str(n) + ')'
     swank_rex(':inspect-in-frame', cmd, get_swank_package(), current_thread, str(n))
 
+def swank_inspector_range():
+    start = int(vim.eval("b:range_start"))
+    end   = int(vim.eval("b:range_end"))
+    cmd = '(swank:inspector-range ' + str(end) + " " + str(end+(end-start)) + ')'
+    swank_rex(':inspector-range', cmd, get_swank_package(), 't')
+
 def swank_quit_inspector():
     swank_rex(':quit-inspector', '(swank:quit-inspector)', 'nil', 't')
 
 
 def swank_list_threads():
     cmd = '(swank:list-threads)'
-    swank_rex(':list-threads', cmd, get_package(), 't')
+    swank_rex(':list-threads', cmd, get_swank_package(), 't')
 
 def swank_kill_thread(index):
     cmd = '(swank:kill-nth-thread ' + str(index) + ')'
-    swank_rex(':kill-thread', cmd, get_package(), 't', str(index))
+    swank_rex(':kill-thread', cmd, get_swank_package(), 't', str(index))
 
 def swank_debug_thread(index):
     cmd = '(swank:debug-nth-thread ' + str(index) + ')'
-    swank_rex(':debug-thread', cmd, get_package(), 't', str(index))
+    swank_rex(':debug-thread', cmd, get_swank_package(), 't', str(index))
 
 ###############################################################################
 # Generic SWANK connection handling
     debug_activated = False
     result = swank_listen()
     pending = actions_pending()
-    while result == '' and pending > 0 and count < listen_retries:
+    while sock and result == '' and pending > 0 and count < listen_retries:
         result = swank_listen()
         pending = actions_pending()
         count = count + 1

plugin/paredit.vim

 " paredit.vim:
 "               Paredit mode for Slimv
-" Version:      0.9.0
-" Last Change:  26 Sep 2011
+" Version:      0.9.3
+" Last Change:  30 Nov 2011
 " Maintainer:   Tamas Kovacs <kovisoft at gmail dot com>
 " License:      This file is placed in the public domain.
 "               No warranty, express or implied.
 
 " Is this a Slimv REPL buffer?
 function! s:IsReplBuffer()
-    if exists( 'g:slimv_repl_dir' ) && exists( 'g:slimv_repl_file' )
-        let repl_name = g:slimv_repl_dir . g:slimv_repl_file
-        return bufnr( repl_name ) == bufnr( '%' )
+    if exists( 'g:slimv_repl_name' )
+        return bufnr( g:slimv_repl_name ) == bufnr( '%' )
     else
-        return bufname( '%' ) =~ '.*\.repl\..*'
+        return 0
     endif
 endfunction
 
     if !s:IsReplBuffer()
         return [0, 0]
     endif
-    return [ line( "'s" ), col( "'s" ) ]
+    return [ b:repl_prompt_line, b:repl_prompt_col ]
 endfunction
 
 " Is the current top level form balanced, i.e all opening delimiters
     let line = getline( '.' )
     let matchb = max( [l-g:paredit_matchlines, 1] )
     let matchf = min( [l+g:paredit_matchlines, line('$')] )
-    let prompt = line( "'s" )
+    let [prompt, cp] = s:GetReplPromptPos()
     if s:IsReplBuffer() && l >= prompt && matchb < prompt
         " Do not go before the last command prompt in the REPL buffer
         let matchb = prompt
 
 " Handle <BS> keypress
 function! PareditBackspace( repl_mode )
-    if a:repl_mode && line( "." ) == line( "'s" ) && col( "." ) <= col( "'s" )
+    let [lp, cp] = s:GetReplPromptPos()
+    if a:repl_mode && line( "." ) == lp && col( "." ) <= cp
         " No BS allowed before the previous EOF mark in the REPL
         " i.e. don't delete Lisp prompt
         return ""
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.