Commits

Tamas Kovacs  committed 4b51e81

Version 0.7.0

Added package/namespace support, new way of refreshing the REPL buffer via autocommands, removed 'RUNNING' mode, cursor stays in the current buffer at evaluation, added option g:slimv_updatetime, removed options related to the old way of refreshing (g:slimv_repl_return and g:slimv_repl_wait), removed debug logging, updated Clojure API to version 1.2, extended keyword definition when selecting symbols, bugfix: defmacro detection problem (again).

  • Participants
  • Parent commits 45b404b

Comments (0)

Files changed (3)

File doc/slimv.txt

-*slimv.txt*                    Slimv                 Last Change: 11 Sep 2010
+*slimv.txt*                    Slimv                 Last Change: 02 Oct 2010
 
 Slimv                                                                  *slimv*
-                               Version 0.6.3
+                               Version 0.7.0
 
 The Superior Lisp Interaction Mode for Vim.
 This plugin is aimed to help Lisp development by interfacing between Vim and
 |slimv-usage|                Usage
 |slimv-repl|                 Lisp REPL inside Vim
 |slimv-clojure|              Clojure support
+|slimv-package|              Package and Namespace handling
 |slimv-profiling|            Profiling
-|slimv-hyperspec|            Hyperspec lookup and Completion
+|slimv-hyperspec|            Hyperspec Lookup and Completion
 |slimv-paredit|              Paredit mode
 |slimv-external|             External utilities
 |slimv-faq|                  Frequently Asked Questions
   - Start Vim or goto an existing instance of Vim.
   - Execute the following command:
 >
-      :helptags <your runtime directory/doc
+       :helptags <your runtime directory>/doc
+
+    (e.g :helptags $VIMRUNTIME/doc)
 <
     This will generate all the help tags for any file located in the doc
     directory.
 
 |g:slimv_ctags|              OS command to generate tags file.
 
-|g:slimv_debug|              Debug log level. Set zero for no debug messages.
-
 |g:slimv_debug_client|       Display the command to start client.
 
 |g:slimv_impl|               The Lisp implementation. Defaults to 'clisp'.
 
 |g:slimv_lisp|               Path for the Lisp interpreter.
 
-|g:slimv_logfile|            Name of the logfile to use for debug messages.
-                             Also see |g:slimv_debug|.
-
-|g:slimv_logfreq|            Flushing frequency to logfile.
-
 |g:slimv_menu|               If nonzero, Slimv menu is added to the Vim menu.
 
+|g:slimv_package|            If nonzero, Slimv package/namespace handling is
+                             switched on.
+
 |g:slimv_port|               TCP/IP port number to use in the Slimv client-
                              server communication.
 
 |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.
 
-|g:slimv_repl_wait|          Number of seconds to wait for the REPL output
-                             to finish. Zero means inifinity.
-
 |g:slimv_repl_wrap|          Set wrap mode for the REPL buffer.
 
+|g:slimv_updatetime|         Alternative value for 'updatetime' during REPL
+                             refresh.
+
 
 Note: Most options require to restart the Vim session when modified.
 
   let g:slimv_client =
   \ 'python ~/.vim/plugin/slimv.py -r "konsole -T Slimv -e @p @s -l clisp -s"'
 
-                                                                *g:slimv_debug*
-Defines the debug log level. Level 0 means no debug messages at all. The debug
-messages go into the logfile defined by |slimv-logfile|.
-
                                                          *g:slimv_debug_client*
 Set this to nonzero if you want to make Vim display the command used to start
 the client and any occurrent error messages. This also makes Slimv keep the
 Slimv client window open on Windows. This setting is useful to debug problems
 when setting up a custom |g:slimv_client| command.
 
-                                                              *g:slimv_logfile*
-Name of the Slimv logfile. Defaults to slimv.log.
-Used only when |g:slimv_debug| level is nonzero.
-
-                                                              *g:slimv_logfreq*
-Flushing frequency to logfile.
-Writing to logfile generates extra Vim messages, so setting a relatively high
-flush frequency helps to get rid of them. The log messages are flushed when
-exiting Vim.
-
                                                                 *g:slimv_ctags*
 It is possible to generate tags file from within Vim. By default Slimv assumes
 that ctags.exe is stored somewhere along with the standard Vim path designated
 by the lack of asynchronous update possibilities in Vim. Sometimes the REPL
 buffer is not perfectly updated, this is the case for example when a Lisp
 program is running too long and it has infrequent outputs only.
-In these situations the REPL buffer can be refreshed manually or the
-separate REPL window can be used for checking the output.
+Slimv refreshes the REPL buffer at every keystroke or when the user doesn't
+press a key for the time specified with 'updatetime'. It is also possible
+to manually refresh the REPL buffer. The default value for 'updatetime' is
+4 secs (=4000 ms), in cases when more precise refreshing is needed you can
+lower the 'updatetime' option, e.g. to one second (=1000 ms):
+    set updatetime=1000
+However, it is not recommended to set this to a much lower value.
+Optionally one may check the output of the separate REPL window.
 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.
 
-                                                            *g:slimv_repl_wait*
-Number of seconds to wait for the REPL output to finish. Zero means inifinity.
-While waiting, the output is displayed continuously. During that time the
-regular Vim commands are not available. For the posssible commands see
-|slimv-repl|.
+                                                           *g:slimv_updatetime*
+The REPL buffer is refreshed at every keystroke or when the user doesn't press
+a key for the time specified with 'updatetime'. Slimv alters the value for
+'updatetime' to a lower value when the REPL buffer is changed, so that the
+update frequency gets higher while there is new REPL output. The original
+value for 'updatetime' is restored when there is no REPL output.
+The g:slimv_updatetime option defines the alternative (lower) value for
+'updatetime' during REPL refresh. If you don't want that Slimv changes
+'updatetime', then set g:slimv_updatetime to zero.
+The default value is 200 (=0.2 sec).
+
+                                                              *g:slimv_package*
+If nonzero then Slimv package/namespace handling is switched on. Please find
+details in the |slimv-package| section.
 
                                                             *g:slimv_repl_wrap*
 Set wrap mode for the REPL buffer, which means the lines longer than the
     ,<Up>   ,rp      Previous Input
     ,<Down> ,rn      Next Input
     ,z      ,rr      Refresh REPL Buffer
-    ,Z      ,rw      Refresh REPL Now
 
 
 Also see |slimv-repl| for additional keybindings valid only in the REPL buffer.
     <Down>         Brings up the next command typed and sent to the Lisp REPL
                    when in the command line.
 
-While waiting for REPL output:
-
-    CTRL-C         Sends a Ctrl-C (SIGINT) signal to the Lisp REPL. Useful for
-                   interrupting a runaway Lisp program from the Lisp REPL
-                   buffer.
-
-    any other key  Stops waiting for REPL output, returns to regular Vim mode.
-                   The key that was pressed is translated and processed by Vim,
-                   according to current the Vim mode.
-                   It is possible to return to the continuous refresh mode
-                   by selecting the "Refresh REPL Buffer" command.
-
 
 ===============================================================================
 CLOJURE SUPPORT                                                 *slimv-clojure*
 
 
 ===============================================================================
+PACKAGE AND NAMESPACE HANDLING                                  *slimv-package*
+
+Slimv has a basic support for handling Lisp packages and Clojure namespaces.
+This means that at every form evaluation Slimv first searches the source file
+for any preceding '(in-package ...)' form for Lisp and '(in-ns ...)' form for
+Clojure. If found then each time the package/namespace definition is evaluated
+first. This way it is possible to randomly re-evaluate forms in a source (or
+multiple sources) that use multiple packages/namespaces, each time the correct
+package/namespace will be used.
+The package/namespace handling can be switched off via the |g:slimv_package|
+option.
+
+
+===============================================================================
 PROFILING                                                     *slimv-profiling*
 
-Slimv is capable pf utilizing SBCL's built-in profiler, and also the same
+Slimv is capable of utilizing SBCL's built-in profiler, and also the same
 monitoring/profiling package (metering.lisp) that is used by SLIME, at least
 for CLISP and maybe for some other Common Lisp implementations.
 Fortunately SLIME's metering.lisp is in public domain, so its current version
 ===============================================================================
 CHANGE LOG                                                    *slimv-changelog*
 
+0.7.0  - Added package/namespace support.
+       - New way of refreshing the REPL buffer via autocommands, removed
+         'RUNNING' mode, cursor stays in the current buffer at evaluation.
+       - Added option g:slimv_updatetime.
+       - Removed options related to the old way of refreshing:
+         g:slimv_repl_return and g:slimv_repl_wait.
+       - Removed debug logging.
+       - Updated Clojure API to version 1.2.
+       - Extended keyword definition when selecting symbols.
+       - Bugfix: defmacro detection problem (again).
+
 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.
 ===============================================================================
 TODO                                                               *slimv-todo*
 
-- 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.
 
 ===============================================================================
 hey, this is a female name in Hungary :) for her support and patience.
 
 ===============================================================================
-vim:tw=78:noet:wrap:ts=8:ft=help:norl:
+vim:tw=80:noet:wrap:ts=8:ft=help:norl:

File ftplugin/slimv-cljapi.vim

 " slimv-cljapi.vim:
 "               Clojure API lookup support for Slimv
-" Version:      0.5.5
-" Last Change:  04 Jan 2010
+" Version:      0.7.0
+" Last Change:  23 Sep 2010
 " Maintainer:   Tamas Kovacs <kovisoft at gmail dot com>
 " License:      This file is placed in the public domain.
 "               No warranty, express or implied.
 
 " Root of the Clojure API
 if !exists( 'g:slimv_cljapi_root' )
-    let g:slimv_cljapi_root = 'http://richhickey.github.com/clojure/'
+    let g:slimv_cljapi_root = 'http://clojure.github.com/clojure/'
 endif
  
 if !exists( 'g:slimv_cljapi_db' )
     \["mod", "clojure.core-api.html\\#clojure.core/mod"],
     \["name", "clojure.core-api.html\\#clojure.core/name"],
     \["namespace", "clojure.core-api.html\\#clojure.core/namespace"],
+    \["namespace-munge", "clojure.core-api.html\\#clojure.core/namespace-munge"],
     \["neg?", "clojure.core-api.html\\#clojure.core/neg?"],
     \["newline", "clojure.core-api.html\\#clojure.core/newline"],
     \["next", "clojure.core-api.html\\#clojure.core/next"],
     \["xml-seq", "clojure.core-api.html\\#clojure.core/xml-seq"],
     \["zero?", "clojure.core-api.html\\#clojure.core/zero?"],
     \["zipmap", "clojure.core-api.html\\#clojure.core/zipmap"],
-    \["inspect", "clojure.inspector-api.html\\#clojure.inspector/inspect"],
-    \["inspect-table", "clojure.inspector-api.html\\#clojure.inspector/inspect-table"],
-    \["inspect-tree", "clojure.inspector-api.html\\#clojure.inspector/inspect-tree"],
     \["load-script", "clojure.main-api.html\\#clojure.main/load-script"],
     \["main", "clojure.main-api.html\\#clojure.main/main"],
     \["repl", "clojure.main-api.html\\#clojure.main/repl"],
     \["skip-if-eol", "clojure.main-api.html\\#clojure.main/skip-if-eol"],
     \["skip-whitespace", "clojure.main-api.html\\#clojure.main/skip-whitespace"],
     \["with-bindings", "clojure.main-api.html\\#clojure.main/with-bindings"],
+    \["apropos", "clojure.repl-api.html\\#clojure.repl/apropos"],
+    \["dir", "clojure.repl-api.html\\#clojure.repl/dir"],
+    \["dir-fn", "clojure.repl-api.html\\#clojure.repl/dir-fn"],
+    \["source", "clojure.repl-api.html\\#clojure.repl/source"],
+    \["source-fn", "clojure.repl-api.html\\#clojure.repl/source-fn"],
     \["difference", "clojure.set-api.html\\#clojure.set/difference"],
     \["index", "clojure.set-api.html\\#clojure.set/index"],
     \["intersection", "clojure.set-api.html\\#clojure.set/intersection"],
     \["rename-keys", "clojure.set-api.html\\#clojure.set/rename-keys"],
     \["select", "clojure.set-api.html\\#clojure.set/select"],
     \["union", "clojure.set-api.html\\#clojure.set/union"],
-    \["e", "clojure.stacktrace-api.html\\#clojure.stacktrace/e"],
-    \["print-cause-trace", "clojure.stacktrace-api.html\\#clojure.stacktrace/print-cause-trace"],
-    \["print-stack-trace", "clojure.stacktrace-api.html\\#clojure.stacktrace/print-stack-trace"],
-    \["print-throwable", "clojure.stacktrace-api.html\\#clojure.stacktrace/print-throwable"],
-    \["print-trace-element", "clojure.stacktrace-api.html\\#clojure.stacktrace/print-trace-element"],
-    \["root-cause", "clojure.stacktrace-api.html\\#clojure.stacktrace/root-cause"],
-    \["apply-template", "clojure.template-api.html\\#clojure.template/apply-template"],
-    \["do-template", "clojure.template-api.html\\#clojure.template/do-template"],
-    \["*load-tests*", "clojure.test-api.html\\#clojure.test/*load-tests*"],
-    \["*stack-trace-depth*", "clojure.test-api.html\\#clojure.test/*stack-trace-depth*"],
-    \["are", "clojure.test-api.html\\#clojure.test/are"],
-    \["assert-any", "clojure.test-api.html\\#clojure.test/assert-any"],
-    \["assert-predicate", "clojure.test-api.html\\#clojure.test/assert-predicate"],
-    \["compose-fixtures", "clojure.test-api.html\\#clojure.test/compose-fixtures"],
-    \["deftest", "clojure.test-api.html\\#clojure.test/deftest"],
-    \["deftest-", "clojure.test-api.html\\#clojure.test/deftest-"],
-    \["file-position", "clojure.test-api.html\\#clojure.test/file-position"],
-    \["function?", "clojure.test-api.html\\#clojure.test/function?"],
-    \["get-possibly-unbound-var", "clojure.test-api.html\\#clojure.test/get-possibly-unbound-var"],
-    \["inc-report-counter", "clojure.test-api.html\\#clojure.test/inc-report-counter"],
-    \["is", "clojure.test-api.html\\#clojure.test/is"],
-    \["join-fixtures", "clojure.test-api.html\\#clojure.test/join-fixtures"],
-    \["report", "clojure.test-api.html\\#clojure.test/report"],
-    \["run-all-tests", "clojure.test-api.html\\#clojure.test/run-all-tests"],
-    \["run-tests", "clojure.test-api.html\\#clojure.test/run-tests"],
-    \["set-test", "clojure.test-api.html\\#clojure.test/set-test"],
-    \["successful?", "clojure.test-api.html\\#clojure.test/successful?"],
-    \["test-all-vars", "clojure.test-api.html\\#clojure.test/test-all-vars"],
-    \["test-ns", "clojure.test-api.html\\#clojure.test/test-ns"],
-    \["test-var", "clojure.test-api.html\\#clojure.test/test-var"],
-    \["testing", "clojure.test-api.html\\#clojure.test/testing"],
-    \["testing-contexts-str", "clojure.test-api.html\\#clojure.test/testing-contexts-str"],
-    \["testing-vars-str", "clojure.test-api.html\\#clojure.test/testing-vars-str"],
-    \["try-expr", "clojure.test-api.html\\#clojure.test/try-expr"],
-    \["use-fixtures", "clojure.test-api.html\\#clojure.test/use-fixtures"],
-    \["with-test", "clojure.test-api.html\\#clojure.test/with-test"],
-    \["with-test-out", "clojure.test-api.html\\#clojure.test/with-test-out"],
-    \["clojure.test.junit", "clojure.test-api.html\\#clojure.test/clojure.test.junit"],
-    \["with-junit-output", "clojure.test-api.html\\#clojure.test/with-junit-output"],
-    \["clojure.test.tap", "clojure.test-api.html\\#clojure.test/clojure.test.tap"],
-    \["print-tap-diagnostic", "clojure.test-api.html\\#clojure.test/print-tap-diagnostic"],
-    \["print-tap-fail", "clojure.test-api.html\\#clojure.test/print-tap-fail"],
-    \["print-tap-pass", "clojure.test-api.html\\#clojure.test/print-tap-pass"],
-    \["print-tap-plan", "clojure.test-api.html\\#clojure.test/print-tap-plan"],
-    \["with-tap-output", "clojure.test-api.html\\#clojure.test/with-tap-output"],
-    \["keywordize-keys", "clojure.walk-api.html\\#clojure.walk/keywordize-keys"],
-    \["macroexpand-all", "clojure.walk-api.html\\#clojure.walk/macroexpand-all"],
-    \["postwalk", "clojure.walk-api.html\\#clojure.walk/postwalk"],
-    \["postwalk-demo", "clojure.walk-api.html\\#clojure.walk/postwalk-demo"],
-    \["postwalk-replace", "clojure.walk-api.html\\#clojure.walk/postwalk-replace"],
-    \["prewalk", "clojure.walk-api.html\\#clojure.walk/prewalk"],
-    \["prewalk-demo", "clojure.walk-api.html\\#clojure.walk/prewalk-demo"],
-    \["prewalk-replace", "clojure.walk-api.html\\#clojure.walk/prewalk-replace"],
-    \["stringify-keys", "clojure.walk-api.html\\#clojure.walk/stringify-keys"],
-    \["walk", "clojure.walk-api.html\\#clojure.walk/walk"],
     \["parse", "clojure.xml-api.html\\#clojure.xml/parse"],
     \["append-child", "clojure.zip-api.html\\#clojure.zip/append-child"],
     \["branch?", "clojure.zip-api.html\\#clojure.zip/branch?"],

File ftplugin/slimv.vim

 " slimv.vim:    The Superior Lisp Interaction Mode for VIM
-" Version:      0.6.3
-" Last Change:  20 Aug 2010
+" Version:      0.7.0
+" Last Change:  02 Oct 2010
 " 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
 " =====================================================================
 
-" Flush log message buffer to logfile
-function! SlimvLogFlush()
-    if exists( 'g:slimv_debug' ) && exists( 'g:slimv_logfile' ) && s:debug_list != []
-        " We need to make a hack: write things into a temporary file
-        " then append temp file contents to the logfile
-        let tmp = tempname()
-        try
-            call writefile( s:debug_list, tmp )
-        finally
-            if g:slimv_windows
-                silent execute '!type ' . tmp . ' >> ' . g:slimv_logfile
-            else
-                silent execute '!cat ' . tmp . ' >> ' . g:slimv_logfile
-            endif
-            call delete(tmp)
-        endtry
-        " Unfortunately I know no way to tell writefile to append the text
-        "call writefile( a:message, g:slimv_logfile )
-        let s:debug_list = []
-    endif
-endfunction
-
-" Write debug message to logfile (message must be a list)
-function! SlimvLogWrite( level, message, immediate )
-    if exists( 'g:slimv_debug' ) && exists( 'g:slimv_logfile' ) && g:slimv_debug >= a:level
-        let s:debug_list = s:debug_list + a:message
-        if len( s:debug_list ) >= g:slimv_logfreq || a:immediate
-            call SlimvLogFlush()
-        endif
-    endif
-endfunction
-
-" Write debug message to logfile with a timestamp
-function! SlimvLog( level, message )
-    if exists( '*strftime' )
-        let time = strftime( '%Y %b %d %X' )
-    else
-        let time = localtime()
-    endif
-    call SlimvLogWrite( a:level, ['***** ' . time] + a:message + [''], 0 )
-endfunction
-
 " Try to autodetect Python executable
 function! SlimvAutodetectPython()
     if executable( 'python' )
     return 'lisp'
 endfunction
 
-" Log global variables to logfile (if debug log set)
-function! SlimvLogGlobals()
-    let info = [ 'Loaded file: ' . fnamemodify( bufname(''), ':p' ) ]
-
-    if exists( 'g:slimv_debug' )
-        call add( info,  printf( 'g:slimv_debug         = %d',    g:slimv_debug ) )
-    endif
-    if exists( 'g:slimv_debug_client' )
-        call add( info,  printf( 'g:slimv_debug_client  = %d',    g:slimv_debug_client ) )
-    endif
-    if exists( 'g:slimv_logfile' )
-        call add( info,  printf( 'g:slimv_logfile       = %s',    g:slimv_logfile ) )
-    endif
-    if exists( 'g:slimv_port' )
-        call add( info,  printf( 'g:slimv_port          = %d',    g:slimv_port ) )
-    endif
-    if exists( 'g:slimv_python' )
-        call add( info,  printf( 'g:slimv_python        = %s',    g:slimv_python ) )
-    endif
-    if exists( 'g:slimv_lisp' )
-        call add( info,  printf( 'g:slimv_lisp          = %s',    g:slimv_lisp ) )
-    endif
-    if exists( 'g:slimv_client' )
-        call add( info,  printf( 'g:slimv_client        = %s',    g:slimv_client ) )
-    endif
-    if exists( 'g:slimv_impl' )
-        call add( info,  printf( 'g:slimv_impl          = %s',    g:slimv_impl ) )
-    endif
-    if exists( 'g:slimv_repl_open' )
-        call add( info,  printf( 'g:slimv_repl_open     = %d',    g:slimv_repl_open ) )
-    endif
-    if exists( 'g:slimv_repl_dir' )
-        call add( info,  printf( 'g:slimv_repl_dir      = %s',    g:slimv_repl_dir ) )
-    endif
-    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
-    if exists( 'g:slimv_repl_wait' )
-        call add( info,  printf( 'g:slimv_repl_wait     = %d',    g:slimv_repl_wait ) )
-    endif
-    if exists( 'g:slimv_repl_wrap' )
-        call add( info,  printf( 'g:slimv_repl_wrap     = %d',    g:slimv_repl_wrap ) )
-    endif
-    if exists( 'g:slimv_keybindings' )
-        call add( info,  printf( 'g:slimv_keybindings   = %d',    g:slimv_keybindings ) )
-    endif
-    if exists( 'g:slimv_menu' )
-        call add( info,  printf( 'g:slimv_menu          = %d',    g:slimv_menu ) )
-    endif
-    if exists( 'g:slimv_ctags' )
-        call add( info,  printf( 'g:slimv_ctags         = %d',    g:slimv_ctags ) )
-    endif
-    if exists( 'g:paredit_mode' )
-        call add( info,  printf( 'g:paredit_mode        = %d',    g:paredit_mode ) )
-    endif
-    if exists( 'g:paredit_matchlines' )
-        call add( info,  printf( 'g:paredit_matchlines  = %d',    g:paredit_matchlines ) )
-    endif
-
-    call SlimvLog( 1, info )
-endfunction
-
-au VimEnter,BufNewFile,BufRead *.lisp call SlimvLogGlobals()
-au VimEnter,BufNewFile,BufRead *.clj  call SlimvLogGlobals()
-au VimLeave *.lisp call SlimvLogFlush()
-au VimLeave *.clj  call SlimvLogFlush()
-
 
 " =====================================================================
 "  Global variable definitions
 " =====================================================================
 
-" Debug level (0 = no debug messages)
-if !exists( 'g:slimv_debug' )
-    let g:slimv_debug = 0
-endif
-
 " Leave client window open for debugging purposes
 " (works only on Windows at the moment)
 if !exists( 'g:slimv_debug_client' )
     let g:slimv_debug_client = 0
 endif
 
-" Logfile name for debug messages
-if !exists( 'g:slimv_logfile' )
-    let g:slimv_logfile = 'slimv.log'
-endif
-
-" Flushing frequency into debug logfile
-if !exists( 'g:slimv_logfreq' )
-    let g:slimv_logfreq = 1
-endif
-
 " TCP port number to use
 if !exists( 'g:slimv_port' )
     let g:slimv_port = 5151
     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
 endif
 
-" How many seconds to wait for the REPL output to finish?
-if !exists( 'g:slimv_repl_wait' )
-    let g:slimv_repl_wait = 10
-endif
-
 " Wrap long lines in REPL buffer
 if !exists( 'g:slimv_repl_wrap' )
     let g:slimv_repl_wrap = 1
 endif
 
+" Alternative value (in msec) for 'updatetime' while the REPL buffer is changing
+if !exists( 'g:slimv_updatetime' )
+    let g:slimv_updatetime = 200
+endif
+
 " Build client command (if not given in vimrc)
 if !exists( 'g:slimv_client' )
     let g:slimv_client = SlimvMakeClientCommand()
     endif
 endif
 
+" Package/namespace handling
+if !exists( 'g:slimv_package' )
+    let g:slimv_package = 1
+endif
+
 
 " =====================================================================
 "  Template definitions
 " Lisp prompt in the last line
 let s:prompt = ''
 
-" The current mode when REPL refresh was started
-let s:insertmode = 0
+" The last update time for the REPL buffer
+let s:last_update = 0
 
-" The last refresh time of the REPL buffer
-let s:last_refresh = 0
+" The last size of the REPL buffer
+let s:last_size = 0
 
-" Debug log buffer
-let s:debug_list = []
-
-" Last used editor window number
-let s:last_winnr = -1
+" The original value for 'updatetime'
+let s:save_updatetime = &updatetime
 
 
 " =====================================================================
 
 " Position the cursor at the end of the REPL buffer
 " Optionally mark this position in Vim mark 's'
-function! SlimvEndOfReplBuffer( markit, insert )
+function! SlimvEndOfReplBuffer( markpos, insert )
     if !g:slimv_repl_open
         " User does not want to display REPL in Vim
         return
     endif
     normal! G$
-    if a:markit
+    if a:markpos
         " Remember the end of the buffer: user may enter commands here
         " Also remember the prompt, because the user may overwrite it
         call setpos( "'s", [0, line('$'), col('$'), 0] )
     set nomodified
 endfunction
 
-" Reload the contents of the REPL buffer from the output file immediately
-function! SlimvRefreshReplBufferNow()
-    let s:last_refresh = localtime()
+" Reload the contents of the REPL buffer from the output file if changed
+function! SlimvRefreshReplBuffer()
+"    if !g:slimv_repl_open || !g:slimv_repl_split
     if !g:slimv_repl_open
         " User does not want to display REPL in Vim
+        " or does not display it in a split window
         return
     endif
 
-    if bufnr( s:repl_name ) != bufnr( "%" )
-        " REPL is not the actual buffer
+    let size = getfsize( s:repl_name )
+    if size == s:last_size
+        " REPL output file did not change since the last refresh
+        if g:slimv_updatetime > 0 && s:last_update < localtime() - 1
+            let &updatetime = s:save_updatetime
+        endif
         return
     endif
+    let s:last_size = size
+
+    let repl_buf = bufnr( s:repl_name )
+    if repl_buf == -1
+        " REPL buffer not loaded
+        return
+    endif
+    let this_buf = bufnr( "%" )
+    if repl_buf != this_buf
+        " Switch to the REPL buffer/window
+        try
+            if g:slimv_repl_split
+                wincmd w
+            else
+                buf #
+            endif
+        catch /.*/
+            " Some Vim versions give an E303 error here
+            " but we don't need a swapfile for the REPL buffer anyway
+        endtry
+    endif
+
+    if g:slimv_updatetime > 0
+        let &updatetime = g:slimv_updatetime
+    endif
+    let s:last_update = localtime()
 
     try
-        execute "silent edit! " . s:repl_name
+        "execute "silent edit! " . s:repl_name
+        "silent execute "view! " . s:repl_name
+        execute "silent view! " . s:repl_name
     catch /.*/
         " Oops, something went wrong, the buffer will not be refreshed this time
     endtry
     syntax on
-    "TODO: use :read instead and keep only the delta in the readout file
+    setlocal autoread
     let insert = 0
     if mode() == 'i' || mode() == 'I'
         let insert = 1
     endif
-    call SlimvEndOfReplBuffer( 1, insert )
-endfunction
+    call SlimvEndOfReplBuffer( 0, insert )
 
-function! SlimvFileChangedShell()
-    call SlimvRefreshReplBufferNow()
+    if repl_buf != this_buf
+        " Switch back to the caller buffer/window
+        if g:slimv_repl_split
+            wincmd w
+        else
+            buf #
+        endif
+    endif
 endfunction
 
-function! SlimvFocusGained()
-    if s:last_refresh < localtime()
-        call SlimvRefreshReplBufferNow()
+" This function re-triggers the CursorHold event
+" after refreshing the REPL buffer
+function! SlimvTimer()
+    call SlimvRefreshReplBuffer()
+    if g:slimv_repl_open
+        if mode() == 'i' || mode() == 'I'
+            " Put an incomplete '<C-O>' command and an Esc into the typeahead buffer
+            call feedkeys("\x0F\e")
+        else
+            " Put an incomplete 'f' command and an Esc into the typeahead buffer
+            call feedkeys("f\e")
+        endif
     endif
 endfunction
 
-" Send interrupt command to REPL
-function! SlimvInterrupt()
-    call SlimvSend( ['SLIMV::INTERRUPT'], 0 )
-    sleep 200m
-    call SlimvRefreshReplBufferNow()
-    startinsert!
+" Switch refresh mode on:
+" refresh REPL buffer on frequent Vim events
+function! SlimvRefreshModeOn()
+    set readonly
+    setlocal autoread
+    execute "au CursorMoved  * :call SlimvRefreshReplBuffer()"
+    execute "au CursorMovedI * :call SlimvRefreshReplBuffer()"
+    execute "au CursorHold   * :call SlimvTimer()"
+    execute "au CursorHoldI  * :call SlimvTimer()"
+    call SlimvRefreshReplBuffer()
 endfunction
 
-" Refresh REPL buffer continuously until no change is detected
-function! SlimvRefreshReplBuffer()
-    if !g:slimv_repl_open
-        " User does not want to display REPL in Vim
-        return
-    endif
-
-    " Refresh REPL buffer for a while until no change is detected
-    let ftime = getftime( s:repl_name )
-    let lastftime = ftime
-    sleep 100m
-    call SlimvRefreshReplBufferNow()
-
-    if s:insertmode
-        " We are in insert mode, let's fake a movement to the right
-        " in order to display the cursor at the right place.
-        " For this we need to set the virtualedit=all option temporarily
-        echon '-- INSERT --'
-        set nomodified
-    else
-        " Inform user that we are in running mode (waiting for REPL output)
-        echon '-- RUNNING --'
-    endif
-
-    " For some reason sometimes a getchar comes with 128 followed by 0.
-    " This is meant to swallow it.
-    while getchar(1) == 128
-        let c = getchar(0)
-    endwhile
+" Switch refresh mode off
+function! SlimvRefreshModeOff()
+    execute "au! CursorMoved"
+    execute "au! CursorMovedI"
+    execute "au! CursorHold"
+    execute "au! CursorHoldI"
+    set noreadonly
 
-    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
-            redraw
-            if getchar(1)
-                break
-            endif
-            sleep 100m
-            let lastftime = ftime
-            let ftime = getftime( s:repl_name )
-            if ftime != lastftime || ftime == localtime() || ftime == localtime()-1
-                " REPL buffer file changed recently, reload it
-                call SlimvRefreshReplBufferNow()
-            endif
-            if g:slimv_repl_wait != 0
-                let wait = wait - 1
-            endif
-        catch /^Vim:Interrupt$/
-            if getchar(1)
-                " Swallow interrupt key
-                let c = getchar(0)
-                if c == 3
-                    " Yes, this was the Ctrl-C, propagate it to the server
-                    " but only if it has not yet been done in this turn
-                    if interrupt == 0
-                        let interrupt = 1
-                        call SlimvHandleInterrupt()
-                        " We override the wait time here to 2 secs
-                        let wait = 20
-                    endif
-                endif
-            endif
-        endtry
-    endwhile
-
-    " Restore everything
-    if synIDattr( synIDtrans( hlID( 'Normal' ) ), 'bg' ) != ''
-        silent! execute 'match Normal ' . m
-    else
-        silent! execute 'match SlimvNormal ' . m
-    endif
-    echon '            '
-
-    if wait == 0 && ftime != lastftime
-        " Time is up and Lisp REPL still did not finish output
-        " Inform user about this and about the non-blocking and blocking refresh keys
-        if g:slimv_keybindings == 1
-            let refresh = "<Leader>z or <Leader>Z"
-        elseif g:slimv_keybindings == 2
-            let refresh = "<Leader>rw or <Leader>rr"
-        else
-            let refresh = ":call SlimvRefreshReplBuffer()"
-        endif
-        call append( '$', "Slimv warning: REPL is busy, refresh display with " . refresh )
-        call SlimvEndOfReplBuffer( 1, s:insertmode )
-    endif
-    if s:insertmode
-        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
+    " Remember the end of the buffer and the actual prompt
+    call setpos( "'s", [0, line('$'), col('$'), 0] )
+    let s:prompt = getline( "'s" )
 endfunction
 
 " Called when entering REPL buffer
 function! SlimvReplEnter()
     call SlimvAddReplMenu()
-    if s:last_refresh < localtime()
-        call SlimvRefreshReplBufferNow()
-    endif
+    execute "au FileChangedRO " . g:slimv_repl_file . " :call SlimvRefreshModeOff()"
+    call SlimvRefreshModeOn()
+    call SlimvEndOfReplBuffer( 1, 0 )
 endfunction
 
 " Called when leaving REPL buffer
     catch /.*/
         " REPL menu not found, we cannot remove it
     endtry
+    call SlimvRefreshModeOn()
+    call SlimvEndOfReplBuffer( 1, 0 )
 endfunction
 
 " Open a new REPL buffer or switch to the existing one
     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
+            execute "silent sview! " . s:repl_name
         else
-            execute "edit " . s:repl_name
+            execute "silent view! " . s:repl_name
         endif
     else
         if g:slimv_repl_split
             let repl_win = bufwinnr( repl_buf )
             if repl_win == -1
                 " Create windows
-                execute "split " . s:repl_name
+                execute "silent sview! " . s:repl_name
             else
                 " Switch to the REPL window
                 if winnr() != repl_win
     endif
 
     " Add keybindings valid only for the REPL buffer
-    inoremap <buffer> <silent>        <CR>   <End><CR><C-O>:call SlimvSendCommand(1,0)<CR>
-    inoremap <buffer> <silent>        <C-CR> <End><CR><C-O>:call SlimvSendCommand(1,1)<CR>
+    inoremap <buffer> <silent>        <CR>   <End><CR><C-O>:call SlimvSendCommand(0)<CR>
+    inoremap <buffer> <silent>        <C-CR> <End><CR><C-O>:call SlimvSendCommand(1)<CR>
     inoremap <buffer> <silent>        <Up>   <C-O>:call SlimvHandleUp()<CR>
     inoremap <buffer> <silent>        <Down> <C-O>:call SlimvHandleDown()<CR>
 
     endif
 
     if g:slimv_keybindings == 1
-        noremap <buffer> <silent> <Leader>.      :call SlimvSendCommand(0,0)<CR>
-        noremap <buffer> <silent> <Leader>/      :call SlimvSendCommand(0,1)<CR>
+        noremap <buffer> <silent> <Leader>.      :call SlimvSendCommand(0)<CR>
+        noremap <buffer> <silent> <Leader>/      :call SlimvSendCommand(1)<CR>
         noremap <buffer> <silent> <Leader><Up>   :call SlimvPreviousCommand()<CR>
         noremap <buffer> <silent> <Leader><Down> :call SlimvNextCommand()<CR>
         noremap <buffer> <silent> <Leader>z      :call SlimvRefresh()<CR>
-        noremap <buffer> <silent> <Leader>Z      :call SlimvRefreshNow()<CR>
     elseif g:slimv_keybindings == 2
-        noremap <buffer> <silent> <Leader>rs     :call SlimvSendCommand(0,0)<CR>
-        noremap <buffer> <silent> <Leader>ro     :call SlimvSendCommand(0,1)<CR>
+        noremap <buffer> <silent> <Leader>rs     :call SlimvSendCommand(0)<CR>
+        noremap <buffer> <silent> <Leader>ro     :call SlimvSendCommand(1)<CR>
         noremap <buffer> <silent> <Leader>rp     :call SlimvPreviousCommand()<CR>
         noremap <buffer> <silent> <Leader>rn     :call SlimvNextCommand()<CR>
         noremap <buffer> <silent> <Leader>rr     :call SlimvRefresh()<CR>
-        noremap <buffer> <silent> <Leader>rw     :call SlimvRefreshNow()<CR>
     endif
 
     if g:slimv_repl_wrap
     hi SlimvCursor term=reverse cterm=reverse gui=reverse
 
     " Add autocommands specific to the REPL buffer
-    execute "au FileChangedShell " . g:slimv_repl_file . " :call SlimvFileChangedShell()"
-    execute "au FocusGained "      . g:slimv_repl_file . " :call SlimvFocusGained()"
+    execute "au FileChangedShell " . g:slimv_repl_file . " :call SlimvRefreshReplBuffer()"
+    execute "au FocusGained "      . g:slimv_repl_file . " :call SlimvRefreshReplBuffer()"
     execute "au BufEnter "         . g:slimv_repl_file . " :call SlimvReplEnter()"
     execute "au BufLeave "         . g:slimv_repl_file . " :call SlimvReplLeave()"
 
     filetype on
+    setlocal autoread
     redraw
+    let s:last_size = 0
 
     call SlimvSend( ['SLIMV::OUTPUT::' . s:repl_name ], 0 )
-    call SlimvEndOfReplBuffer( 0, 0 )
+    call SlimvRefreshReplBuffer()
 endfunction
 
 " Select symbol under cursor and copy it to register 's'
 function! SlimvSelectSymbolExt()
     let oldkw = &iskeyword
     if SlimvGetFiletype() == 'clojure'
-        let &iskeyword = oldkw . ',~,#,&,|,{,}'
+        setlocal iskeyword+=~,#,&,\|,{,},!,?
     else
-        let &iskeyword = oldkw . ',~,#,&,|,{,},[,]'
+        setlocal iskeyword+=~,#,&,\|,{,},[,],!,?
     endif
     normal! viw"sy
     let &iskeyword = oldkw
     return getreg( '"s' )
 endfunction
 
+" Find the given string backwards and put it in front of the current selection
+" if it is a valid Lisp form (i.e. not inside comment or string)
+function! SlimvFindAddSel( string )
+    normal ms
+    let found = 0
+    while search( '(\s*' . a:string . '\s', 'bcW' )
+        " Search for the previos occurrence
+        if synIDattr( synID( line('.'), col('.'), 0), 'name' ) !~ '[Ss]tring\|[Cc]omment'
+            " It is not inside a comment or string
+            let found = 1
+            break
+        endif
+    endwhile
+    if found
+        " Put the form just found at the beginning of the selection
+        let sel = SlimvGetSelection()
+        normal! v%"sy
+        call setreg( '"s', SlimvGetSelection() . "\n" . sel )
+        normal `s
+    endif
+endfunction
+
+" Find and add language specific package/namespace definition before the
+" cursor position and if exists then add it in front of the current selection
+function! SlimvFindPackage()
+    if !g:slimv_package
+        return
+    endif
+    if SlimvGetFiletype() == 'clojure'
+        call SlimvFindAddSel( 'in-ns' )
+    else
+        call SlimvFindAddSel( 'in-package' )
+    endif
+endfunction
+
 " Send argument to Lisp server for evaluation
 function! SlimvSend( args, open_buffer )
     call SlimvClientCommand()
     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
+    let repl_win = bufwinnr( repl_buf )
 
-    if a:open_buffer
+    if a:open_buffer && ( repl_buf == -1 || ( g:slimv_repl_split && repl_win == -1 ) )
         call SlimvOpenReplBuffer()
     endif
 
 
     let tmp = tempname()
     try
-        call SlimvLog( 2, a:args )
         call writefile( ar, tmp )
 
         " Send the file to the client for evaluation
     endtry
 
     if a:open_buffer
+        " Wait a little for the REPL output and refresh REPL buffer
+        " then return to the caller buffer/window
         call SlimvRefreshReplBuffer()
+        if g:slimv_repl_split && repl_win == -1
+            execute "normal! \<C-w>p"
+        elseif repl_buf == -1
+            buf #
+        endif
     endif
 endfunction
 
     call SlimvSend( a:args, g:slimv_repl_open )
 endfunction
 
+" Send interrupt command to REPL
+function! SlimvInterrupt()
+    call SlimvSend( ['SLIMV::INTERRUPT'], 0 )
+    call SlimvRefreshReplBuffer()
+    startinsert!
+endfunction
+
 " Set command line after the prompt
 function! SlimvSetCommandLine( cmd )
     let line = getline( "." )
 endfunction
 
 " Send command line to REPL buffer
-" Arguments: insert = we are in insertmode, close = add missing closing parens
-function! SlimvSendCommand( insert, close )
+" Arguments: close = add missing closing parens
+function! SlimvSendCommand( close )
+    call SlimvRefreshModeOn()
     let lastline = line( "'s" )
     let lastcol  =  col( "'s" )
     if lastline > 0
             if paren == 0
                 " Expression finished, let's evaluate it
                 " but first add it to the history
-                let s:insertmode = a:insert
                 call SlimvAddHistory( cmd )
                 call SlimvEval( cmd )
             elseif paren < 0
 " Handle interrupt (Ctrl-C) keypress in the REPL buffer
 function! SlimvHandleInterrupt()
     call SlimvSend( ['SLIMV::INTERRUPT'], 0 )
-    sleep 200m
-    call SlimvRefreshReplBufferNow()
+    call SlimvRefreshReplBuffer()
 endfunction
 
 " Start and connect slimv server
 " This is a quite dummy function that just evaluates the empty string
 function! SlimvConnectServer()
-    call SlimvEval( [''] )
+    "call SlimvEval( [''] )
+    call SlimvSend( ['SLIMV::OUTPUT::' . s:repl_name ], 0 )
 endfunction
 
 " Refresh REPL buffer continuously
         " REPL is not the current window, activate it
         call SlimvOpenReplBuffer()
     endif
-    call SlimvRefreshReplBuffer()
-endfunction
-
-" Refresh REPL buffer continuously
-function! SlimvRefreshNow()
-    if bufnr( s:repl_name ) == -1
-        " REPL not opened, no need to refresh
-        return
-    endif
-    if bufnr( s:repl_name ) != bufnr( "%" )
-        " REPL is not the current window, activate it
-        call SlimvOpenReplBuffer()
-    endif
-    call SlimvRefreshReplBufferNow()
 endfunction
 
 " Get the last region (visual block)
         let lines[len(lines)-1] = ''
     endif
     let lines[0] = lines[0][firstcol : ]
+
+    " Find and add package/namespace definition in front of the region
+    if g:slimv_package
+        call setreg( '"s', '' )
+        call SlimvFindPackage()
+        let sel = SlimvGetSelection()
+        if sel != ''
+            let lines = [sel] + lines
+        endif
+    endif
     return lines
 endfunction
 
 " Evaluate top level form at the cursor pos
 function! SlimvEvalDefun()
     call SlimvSelectToplevelForm()
+    call SlimvFindPackage()
     call SlimvEvalSelection()
 endfunction
 
 " Evaluate last expression
 function! SlimvEvalLastExp()
     call SlimvSelectForm()
+    call SlimvFindPackage()
     call SlimvEvalSelection()
 endfunction
 
 " Evaluate and pretty print last expression
 function! SlimvPprintEvalLastExp()
     call SlimvSelectForm()
+    call SlimvFindPackage()
     call SlimvEvalForm1( g:slimv_template_pprint, SlimvGetSelection() )
 endfunction
 
 function! SlimvMacroexpandGeneral( command )
     normal! 99[(
     let line = getline( "." )
-    if match( line, 'defmacro\s' ) < 0
+    if match( line, '(\s*defmacro\s' ) < 0
         " The form does not contain 'defmacro', put it in a macroexpand block
         call SlimvSelectForm()
         let m = "(" . a:command . " '" . SlimvGetSelection() . ")"
 function! SlimvCompileDefun()
     "TODO: handle double quote characters in form
     call SlimvSelectToplevelForm()
+    call SlimvFindPackage()
     call SlimvEvalForm1( g:slimv_template_compile_string, SlimvGetSelection() )
 endfunction
 
         execute ':map <Leader>\ :emenu REPL.' . nr2char( &wildcharm )
     endif
 
-    amenu &REPL.Send-&Input                            :call SlimvSendCommand(0,0)<CR>
-    amenu &REPL.Cl&ose-Send-Input                      :call SlimvSendCommand(0,1)<CR>
+    amenu &REPL.Send-&Input                            :call SlimvSendCommand(0)<CR>
+    amenu &REPL.Cl&ose-Send-Input                      :call SlimvSendCommand(1)<CR>
     amenu &REPL.Interrup&t-Lisp-Process                <Esc>:<C-U>call SlimvInterrupt()<CR>
     amenu &REPL.-REPLSep-                              :
     amenu &REPL.&Previous-Input                        :call SlimvPreviousCommand()<CR>
     amenu &REPL.&Next-Input                            :call SlimvNextCommand()<CR>
-    menu  &REPL.&Refresh                               :call SlimvRefresh()<CR>
-    amenu &REPL.Refresh-No&w                           :call SlimvRefreshNow()<CR>
+    amenu &REPL.&Refresh                               :call SlimvRefresh()<CR>
 endfunction