1. lotabout
  2. slimv-newlisp

Commits

Tamas Kovacs  committed 45b404b

Version 0.6.3

Added option to return cursor to the editor window from REPL buffer after evaluating an s-expression, Wrap: if standing on a paren then wrap the whole s-expression, Wrap selection: exit visual mode after command, Bugfixes: inserting double quotes in paredit mode (like "\""), dd in paredit mode when unbalanced form is inside comment, reopen REPL buffer after closing it via ":q", comment and string detection error with noignorecase setting, wrong positioning when moving parenthesis to the right, defmacro detection problem, paredit wrap selection missed last character when 'selection' was not "exclusive".

  • Participants
  • Parent commits 812a557
  • Branches master

Comments (0)

Files changed (3)

File doc/slimv.txt

View file
-*slimv.txt*                    Slimv                 Last Change: 09 Jun 2010
+*slimv.txt*                    Slimv                 Last Change: 11 Sep 2010
 
 Slimv                                                                  *slimv*
-                               Version 0.6.2
+                               Version 0.6.3
 
 The Superior Lisp Interaction Mode for Vim.
 This plugin is aimed to help Lisp development by interfacing between Vim and
   - Enter path definitions into your vimrc (if the default values are not
     valid for your Vim/Python/Lisp installation, which is highly probable).
     See |slimv-customization| below on how to do this.
+  - On Linux some login shells (like fish) might be incompatible with the Vim
+    temporary file generation, which results in getting random E484 errors.
+    This is because Vim expects a POSIX-compliant shell and the problem might
+    occur in other Vim scripts as well.
+    One solution is to add a similar block to the top of .vimrc:
+
+        if $SHELL =~ 'bin/fish'
+            set shell=/bin/sh
+        endif
+
 
 Upgrade from previous script versions:
 
 |g:slimv_repl_open|          If nonzero, Slimv opens the Lisp REPL buffer
                              inside Vim when the server is started.
 
+|g:slimv_repl_return|        If nonzero, the cursor is returned to the editor
+                             window from the REPL buffer after evaluation.
+
 |g:slimv_repl_split|         Open the Lisp REPL buffer in a split window
                              or in a separate buffer.
 
 The |g:slimv_repl_open| = 0 option can be used to disable the built-in REPL
 buffer, so that only the separate REPL window is opened.
 
+                                                          *g:slimv_repl_return*
+By default the cursor is placed in the REPL buffer and it stays there when
+evaluating a form in the editor window. If |g:slimv_repl_open| is set then
+the cursor is returned to the editor window after the evaluation is performed
+and the timeout defined in |g:slimv_repl_wait| elapsed.
+
                                                            *g:slimv_repl_split*
 Open the Lisp REPL buffer in a split window or in a separate buffer in Vim.
 Used only when |g:slimv_repl_open| is nonzero.
 built in keybinding set (|g:slimv_keybindings|=2) for Slimv are the following.
 Please note that the leading ',' key below refers to <Leader>, which is set
 by Slimv to ',' by default.
+Vim defines timeout values for mapped key sequences. If you find that Vim does
+not allow you enough time between pressing ',' and the last key(s) of the
+sequence, then you may want to fine tune these Vim options:
+|timeout|, |ttimeout|, |timeoutlen|, |ttimeoutlen|.
 
     Set#1   Set#2    Command
     ---------------------------------------------------
     <C-X><C-O>       Complete-Symbol
 
     Evaluation commands:
-    ,d      ,ed      Eval Defun
-    ,e      ,ee      Eval Last Expression
+    ,d      ,ed      Eval Defun (current top level form)
+    ,e      ,ee      Eval Last Expression (current subform)
     ,E      ,ep      Pprint Eval Last Expression
-    ,r      ,er      Eval Region
+    ,r      ,er      Eval Region (visual selection)
     ,b      ,eb      Eval Buffer
     ,v      ,ei      Interactive Eval
     ,u      ,eu      Undefine Function
     ,Z      ,rw      Refresh REPL Now
 
 
-Also see *slimv-repl* for additional keybindings valid only in the REPL buffer.
+Also see |slimv-repl| for additional keybindings valid only in the REPL buffer.
 
 
 ===============================================================================
 ===============================================================================
 CHANGE LOG                                                    *slimv-changelog*
 
+0.6.3  - Added option g:slimv_repl_return to return cursor to the editor window
+         from REPL buffer after evaluating an s-expression.
+       - Wrap: if standing on a paren then wrap the whole s-expression.
+       - Wrap selection: exit visual mode after command.
+       - Bugfix: inserting double quotes in paredit mode (like "\"").
+       - Bugfix: dd in paredit mode when unbalanced form is inside comment.
+       - Bugfix: reopen REPL buffer after closing it via :q.
+       - Bugfix: comment and string detection error with noignorecase setting
+         (thanks to Brian Kropf).
+       - Bugfix: wrong positioning when moving parenthesis to the right.
+       - Bugfix: defmacro detection problem (thanks to Philipp Marek).
+       - Bugfix: paredit wrap selection missed last character when 'selection'
+         was not "exclusive".
+
 0.6.2  - Added support for Mac OS X via Terminal.app (on behalf of Vlad Hanciuta).
        - Added string "clj" as a detector for Clojure (by Vlad Hanciuta).
        - Bugfix: paredit wrap function missed last character when 'selection'
 ===============================================================================
 TODO                                                               *slimv-todo*
 
-- Add Compile System.
-- Add Cross Reference functions.
-- Add Debugger.
-- Start client and server separately having two simpler commands for client
-  and server startup, instead of the existing g:slimv_client solution.
-- Implement an own main loop in Vim for the REPL buffer, poll REPL output
-  regularly, handle all Vim keypresses and commands inside the main loop,
-  continuously update the REPL buffer.
+- Add package and namespace support.
+- Add a new way of refreshing the REPL buffer via checktime and autoread.
+- Update to Clojure 1.2.
 - Add Swank support, i.e. send commands to SLIME's Swank server.
-- Rewrite client/server in Lisp, so that no Python would be needed,
-- Or put the (Python) client part back into the .vim script, rewrite only the
-  server part in Lisp.
-- Handle specific REPL output in Vim (like compilation notes).
-- Add all paredit.el functions.
 
 ===============================================================================
 CREDITS                                                         *slimv-credits*
 Taylor R. Campbell for the Emacs paredit.el script.
 Thanks to the Vim community for testing, commenting and patching the script,
 especially to Philipp Marek, Vlad Hanciuta, Marcin Fatyga, Dmitry Petukhov,
-Daniel Solano G�mez.
+Daniel Solano G�mez, Brian Kropf, Len Weincier.
 Last but not least many thanks to my wife Andrea (for the Italians out there:
 hey, this is a female name in Hungary :) for her support and patience.
 

File ftplugin/slimv.vim

View file
 " slimv.vim:    The Superior Lisp Interaction Mode for VIM
-" Version:      0.6.2
-" Last Change:  09 Jun 2010
+" Version:      0.6.3
+" Last Change:  20 Aug 2010
 " Maintainer:   Tamas Kovacs <kovisoft at gmail dot com>
 " License:      This file is placed in the public domain.
 "               No warranty, express or implied.
     if exists( 'g:slimv_repl_file' )
         call add( info,  printf( 'g:slimv_repl_file     = %s',    g:slimv_repl_file ) )
     endif
+    if exists( 'g:slimv_repl_return' )
+        call add( info,  printf( 'g:slimv_repl_return   = %d',    g:slimv_repl_return ) )
+    endif
     if exists( 'g:slimv_repl_split' )
         call add( info,  printf( 'g:slimv_repl_split    = %d',    g:slimv_repl_split ) )
     endif
     let g:slimv_repl_file = b:SlimvREPLFile()
 endif
 
+" Return from the REPL buffer to the calling Vim buffer/window after each evaluation
+if !exists( 'g:slimv_repl_return' )
+    let g:slimv_repl_return = 0
+endif
+
 " Shall we open REPL buffer in split window?
 if !exists( 'g:slimv_repl_split' )
     let g:slimv_repl_split = 1
 " Debug log buffer
 let s:debug_list = []
 
+" Last used editor window number
+let s:last_winnr = -1
+
 
 " =====================================================================
 "  General utility functions
     let m = '/\%#/'
     let interrupt = 0
     let wait = g:slimv_repl_wait * 10   " number of cycles to wait for refreshing the REPL buffer
+    "TODO: do not stop refreshing while we have output from REPL
+    "i.e. start counting wait time after output is stopped.
     while wait > 0 || g:slimv_repl_wait == 0
         try
             silent! execute 'match SlimvCursor ' . m
         startinsert!
         let s:insertmode = 0
     endif
+
+    if g:slimv_repl_return && g:slimv_repl_split && s:last_winnr != -1
+        execute "normal! \<C-w>p"
+    endif
+    let s:last_winnr = -1
 endfunction
 
 " Called when entering REPL buffer
     if repl_buf == -1
         " Create a new REPL buffer
         if g:slimv_repl_split
+            let s:last_winnr = bufwinnr( "%" ) + 1
             execute "split " . s:repl_name
         else
             execute "edit " . s:repl_name
             let repl_win = bufwinnr( repl_buf )
             if repl_win == -1
                 " Create windows
-                execute "split +buffer " . repl_buf
+                execute "split " . s:repl_name
             else
                 " Switch to the REPL window
                 if winnr() != repl_win
         return
     endif
 
+    let repl_buf = bufnr( s:repl_name )
+    if repl_buf != -1
+        let winnr = bufwinnr( "%" )
+        if winnr != bufwinnr( repl_buf )
+            let s:last_winnr = winnr
+        endif
+    endif
+
     if a:open_buffer
         call SlimvOpenReplBuffer()
     endif
 function! SlimvMacroexpandGeneral( command )
     normal! 99[(
     let line = getline( "." )
-    if match( line, 'defmacro' ) < 0
+    if match( line, 'defmacro\s' ) < 0
         " The form does not contain 'defmacro', put it in a macroexpand block
         call SlimvSelectForm()
         let m = "(" . a:command . " '" . SlimvGetSelection() . ")"

File plugin/paredit.vim

View file
 " paredit.vim:
 "               Paredit mode for Slimv
-" Version:      0.6.2
-" Last Change:  26 May 2010
+" Version:      0.6.3
+" Last Change:  04 Sep 2010
 " Maintainer:   Tamas Kovacs <kovisoft at gmail dot com>
 " License:      This file is placed in the public domain.
 "               No warranty, express or implied.
 " =====================================================================
 
 " Skip matches inside string or comment
-let s:skip_c  = 'synIDattr(synID(line("."), col("."), 0), "name") =~ "comment"'
-let s:skip_sc = 'synIDattr(synID(line("."), col("."), 0), "name") =~ "string\\|comment"'
+let s:skip_c  = 'synIDattr(synID(line("."), col("."), 0), "name") =~ "[Cc]omment"'
+let s:skip_sc = 'synIDattr(synID(line("."), col("."), 0), "name") =~ "[Ss]tring\\|[Cc]omment"'
 
 " Regular expressions to identify special characters combinations used by paredit
 "TODO: add curly brace
 endfunction
 
 " Does the current syntax item match the given regular expression?
-function! s:SynIDMatch( regexp )
+function! s:SynIDMatch( regexp, match_eol )
     let line = line('.')
     let col  = col('.')
-    if col > len( getline( line ) )
+    if a:match_eol && col > len( getline( line ) )
         let col = col - 1
     endif
     return synIDattr( synID( line, col, 0), 'name' ) =~ a:regexp
 
 " Is the current cursor position inside a comment?
 function! s:InsideComment()
-    return s:SynIDMatch( 'comment' )
+    return s:SynIDMatch( '[Cc]omment', 1 )
 endfunction
 
 " Is the current cursor position inside a string?
 function! s:InsideString()
-    return s:SynIDMatch( 'string' )
-endfunction
-
-" Is the current cursor position inside a comment or string?
-function! s:InsideCommentOrString()
-    return s:SynIDMatch( 'string\|comment' )
+    return s:SynIDMatch( '[Ss]tring', 0 )
 endfunction
 
 " Autoindent current top level form
 
 " Insert opening type of a paired character, like ( or [.
 function! PareditInsertOpening( open, close )
-    if !g:paredit_mode || s:InsideCommentOrString() || !s:IsBalanced()
+    if !g:paredit_mode || s:InsideComment() || s:InsideString() || !s:IsBalanced()
         return a:open
     endif
-    let retval = a:open . a:close . "\<Left>"
     let line = getline( '.' )
     let pos = col( '.' ) - 1
-    if line[pos] !~ s:any_wsclose_char
+    if line[pos] !~ s:any_wsclose_char && pos < len( line )
         " Add a space after if needed
         let retval = a:open . a:close . " \<Left>\<Left>"
     else
 
 " Insert closing type of a paired character, like ) or ].
 function! PareditInsertClosing( open, close )
-    if !g:paredit_mode || s:InsideCommentOrString() || !s:IsBalanced()
+    if !g:paredit_mode || s:InsideComment() || s:InsideString() || !s:IsBalanced()
         return a:close
     endif
     let line = getline( '.' )
         let line = getline( '.' )
         let pos = col( '.' ) - 1
         "TODO: skip comments in search(...)
-        if line[pos] == '"'
+        if pos > 0 && line[pos-1] == '\' && (pos < 2 || line[pos-2] != '\')
+            " About to enter a \" inside a string
+            return '"'
+        elseif line[pos] == '"'
             " Standing on a ", just move to the right
             return "\<Right>"
-        elseif (pos > 0 && line[pos-1] == '\') || search('[^\\]"\|^"', 'nW') == 0
+        elseif search('[^\\]"\|^"', 'nW') == 0
             " We don't have any closing ", insert one
             return '"'
         else
     while col( '.' ) != lastcol || len( getline( '.' ) ) != lastlen
         let lastcol = col( '.' )
         let lastlen = len( getline( '.' ) )
-        call s:EraseFwd( 1, a:startcol )
+        let line = getline( '.' )
+        if s:InsideComment()
+            normal! D
+            if v:count == 0
+                return
+            endif
+        else
+            call s:EraseFwd( 1, a:startcol )
+        endif
     endwhile
 endfunction
 
                 if !a:skip_whitespc && !s:InsideString()
                     " Next symbol ended with comment
                     call setpos( '.', [0, l0, c0, 0] )
-                    return [l, c]
+                    return [l, c + ([l, c] == [l1, c1])]
                 endif
             endif
             normal! 0j0
         " Do not go after the last command prompt in the REPL buffer
         return
     endif
-    if opening && c0 > 0 && line[c0-2] =~ s:any_macro_prefix
+    if opening && c0 > 1 && line[c0-2] =~ s:any_macro_prefix
         call s:MoveChar( l0, c0-1, l1, c1 )
         call s:MoveChar( l0, c0-1, l1, c1 + (l0 != l1) )
         let len = 2
         execute "normal! a "
         normal! h
     endif
-    return
 endfunction
 
 " Find closing of the innermost structure: (...) or [...]
 
 " Join two neighboring lists or strings
 function! PareditJoin()
-    if !g:paredit_mode || s:InsideCommentOrString()
+    if !g:paredit_mode || s:InsideComment() || s:InsideString()
         return
     endif
 
     let l1 = line( "'>" )
     let c0 = col( "'<" )
     let c1 = col( "'>" )
+    if &selection == 'inclusive'
+        let c1 = c1 + 1
+    endif
     if [l0, c0] == [0, 0] || [l1, c1] == [0, 0]
         " No selection
         return
 " Keep visual mode
 function! PareditWrapSelection( open, close )
     call s:WrapSelection( a:open, a:close )
-    if line( "'<" ) == line( "'>" )
-        normal! gvolol
-    else
-        normal! gvolo
-    endif
 endfunction
 
 " Wrap current symbol in parens of the given kind
+" If standing on a paren then wrap the whole s-expression
 " Stand on the opening paren (if not wrapping in "")
 function! PareditWrap( open, close )
-    let sel = &selection
-    let &selection = 'exclusive'
-    execute "normal! " . "viw\<Esc>"
+    if a:open != '"' && getline('.')[col('.') - 1] =~ s:any_openclose_char
+        execute "normal! " . "v%\<Esc>"
+    else
+        execute "normal! " . "viw\<Esc>"
+    endif
     call s:WrapSelection( a:open, a:close )
     if a:open != '"'
         normal! %
     endif
-    let &selection = sel
 endfunction
 
 " Splice current list into the containing list