Commits

Tamas Kovacs  committed 37cb969

Version 0.1.4

Ctrl+C is propagated to Lisp REPL, so it is possible to interrupt a running program. Bugfix: delayed display of last line in REPL window on Linux.

  • Participants
  • Parent commits 7c7a679

Comments (0)

Files changed (3)

File doc/slimv.txt

-*slimv.txt*                    Slimv                 Last Change: 17 Feb 2009
+*slimv.txt*                    Slimv                 Last Change: 21 Feb 2009
 
 Slimv                                                                  *slimv*
-                               Version 0.1.3
+                               Version 0.1.4
 
 The Superior Lisp Interaction Mode for Vim.
 This plugin is aimed to help Lisp development by interfacing between Vim and
 All you need to know then is the list of possible Slimv commands, how to
 enter them and under what conditions.
 
+It is possible to interrupt a running Lisp program by pressing Ctrl+C,
+at least in some Lisp implementations, like CLISP (does not work for example
+with SBCL).
+
+To end the Lisp session press EOF (Ctrl+D on Linux, Ctrl+Z on Windows)
+in the Lisp REPL window. After exiting the REPL it is possible to open
+a new one from Vim the same way as before.
+
 
 ===============================================================================
 FAQ                                                                 *slimv-faq*
 ===============================================================================
 CHANGE LOG                                                    *slimv-changelog*
 
+0.1.4  - Corrected the delayed display of last line in REPL window on Linux.
+       - Ctrl+C is propagated to Lisp REPL, so it is possible to interrupt
+         a running program. Does not work however with some Lisp
+         implementations (like SBCL).
+
 0.1.3  - Handle DOS and Unix style newlines produced by various
          Lisp implementations on Windows.
        - Do not write debug logfile when debug level is zero.

File plugin/slimv.py

 #
 # Client/Server code for Slimv
 # slimv.py:     Client/Server code for slimv.vim plugin
-# Version:      0.1.3
-# Last Change:  17 Feb 2009
+# Version:      0.1.4
+# Last Change:  21 Feb 2009
 # Maintainer:   Tamas Kovacs <kovisoft at gmail dot com>
 # License:      This file is placed in the public domain.
 #               No warranty, express or implied.
     # Start server
     #TODO: put in try-block
     if mswindows:
-        #from win32process import CREATE_NEW_CONSOLE
         CREATE_NEW_CONSOLE = 16
         server = Popen( cmd, creationflags=CREATE_NEW_CONSOLE )
     else:
         while self.buflen < l:
             try:
                 # Write all lines in the buffer to the display
-                output.write( self.buffer[self.buflen] )
+                #output.write( self.buffer[self.buflen] )
+                os.write( output.fileno(), self.buffer[self.buflen] )
                 self.buflen = self.buflen + 1
             except:
                 break
             conn.close()
 
 
-class input_listener( Thread ):
-    """Server thread to receive input from console.
+class output_listener( Thread ):
+    """Server thread to receive REPL output.
     """
 
-    def __init__ ( self, inp, buffer ):
+    def __init__ ( self, out, buffer ):
         Thread.__init__( self )
-        self.inp = inp
+        self.out = out
         self.buffer = buffer
 
     def run( self ):
 
         while not terminate:
             try:
-                # Read input from the console and write it
-                # to the stdin of REPL
-                text = raw_input()
-                self.inp.write   ( text + newline )
-
-            except EOFError:
-                # EOF (Ctrl+Z on Windows, Ctrl+D on Linux) pressed?
-                terminate = 1
-            except KeyboardInterrupt:
-                # Interrupted from keyboard (Ctrl+Break, Ctrl+C)?
-                terminate = 1
+                # Read input from the stdout of REPL
+                # and write it to the display (display queue buffer)
+                if mswindows:
+                    c = self.out.read( 1 )
+                    if ord( c ) == 0x0D:
+                        # Special handling of 0x0D+0x0A on Windows
+                        c2 = self.out.read( 1 )
+                        if ord( c2 ) == 0x0A:
+                            self.buffer.write( '\n' )
+                        else:
+                            self.buffer.write( c )
+                            self.buffer.write( c2 )
+                    else:
+                        self.buffer.write( c )
+                else:
+                    # On Linux set read mode to non blocking
+                    import fcntl, select
+                    flag = fcntl.fcntl(self.out.fileno(), fcntl.F_GETFL)
+                    fcntl.fcntl(self.out.fileno(), fcntl.F_SETFL, flag | os.O_NONBLOCK)
+
+                    r = select.select([self.out.fileno()], [], [], 0)[0]
+                    if r:
+                        c = os.read( self.out.fileno(), 1 )
+                        self.buffer.write( c )
+            except:
+                break
 
 
-class output_listener( Thread ):
-    """Server thread to receive REPL output.
+class buffer_listener( Thread ):
+    """Server thread to read and display contents of the output buffer.
     """
 
-    def __init__ ( self, out, buffer ):
+    def __init__ ( self, buffer ):
         Thread.__init__( self )
-        self.out = out
         self.buffer = buffer
 
     def run( self ):
 
         while not terminate:
             try:
-                # Read input from the stdout of REPL
-                # and write it to the display (display queue buffer)
-                c = self.out.read(1)
-                if mswindows and ord( c ) == 0x0D:
-                    # Special handling of 0x0D+0x0A on Windows
-                    c2 = self.out.read(1)
-                    if ord( c2 ) == 0x0A:
-                        self.buffer.write( '\n' )
-                    else:
-                        self.buffer.write( c )
-                        self.buffer.write( c2 )
-                else:
-                    self.buffer.write( c )
+                # Constantly display messages in the display queue buffer
+                #TODO: it would be better having some wakeup mechanism here
+                time.sleep(0.01)
+                self.buffer.read_and_display( sys.stdout )
+
             except:
-                #TODO: should we set terminate=1 here as well?
-                break
+                # We just ignore any errors here
+                pass
 
 
 def server():
     cmd = shlex.split( lisp_path.replace( '\\', '\\\\' ) )
 
     # Start Lisp
-    if mswindows:
-        #from win32con import CREATE_NO_WINDOW
-        CREATE_NO_WINDOW = 134217728
-        repl = Popen( cmd, stdin=PIPE, stdout=PIPE, stderr=STDOUT, creationflags=CREATE_NO_WINDOW )
-    else:
-        repl = Popen( cmd, stdin=PIPE, stdout=PIPE, stderr=STDOUT )
+    repl = Popen( cmd, stdin=PIPE, stdout=PIPE, stderr=STDOUT )
 
     buffer = repl_buffer()
 
     # Create and start helper threads
-    ol = output_listener( repl.stdout, buffer )
-    ol.start()
-    il = input_listener( repl.stdin, buffer )
-    il.start()
     sl = socket_listener( repl.stdin, buffer )
     sl.start()
+    ol = output_listener( repl.stdout, buffer )
+    ol.start()
+    bl = buffer_listener( buffer )
+    bl.start()
 
     # Allow Lisp to start, confuse it with some fancy Slimv messages
     sys.stdout.write( ";;; Slimv server is started on port " + str(PORT) + newline )
     # Main server loop
     while not terminate:
         try:
-            # Constantly display messages in the display queue buffer
-            #TODO: it would be better having some wakeup mechanism here
-            time.sleep(0.01)
-            buffer.read_and_display( sys.stdout )
-
+            # Read input from the console and write it
+            # to the stdin of REPL
+            text = raw_input()
+            repl.stdin.write( text + newline )
+            buffer.write( text + newline )
         except EOFError:
             # EOF (Ctrl+Z on Windows, Ctrl+D on Linux) pressed?
             terminate = 1
         except KeyboardInterrupt:
-            # Interrupted from keyboard (Ctrl+Break, Ctrl+C)?
-            terminate = 1
+            # Interrupted from keyboard (Ctrl+C)?
+            # We just ignore it here, it will be propagated to the child anyway
+            pass
 
     # The socket is opened here only for waking up the server thread
     # in order to recognize the termination message

File plugin/slimv.vim

 " slimv.vim:    The Superior Lisp Interaction Mode for VIM
-" Version:      0.1.3
-" Last Change:  17 Feb 2009
+" Version:      0.1.4
+" Last Change:  21 Feb 2009
 " Maintainer:   Tamas Kovacs <kovisoft at gmail dot com>
 " License:      This file is placed in the public domain.
 "               No warranty, express or implied.
 endfunction
 
 " Build the command to start the client
-function! SlimvClientCommand()
+function! SlimvMakeClientCommand()
     if g:slimv_python == '' || g:slimv_lisp == ''
         " We don't have enough information to build client command
         return ''
         "       \ '"console -w Slimv -r \"/k @p @s -l ' . g:slimv_lisp . ' -s\""'
     else
         return g:slimv_python . ' ' . g:slimv_path . port . ' -l ' . g:slimv_lisp
+endfunction
+
+function! SlimvClientCommand()
+    if g:slimv_client == ''
+        " No command to start client, we are clueless, ask user for assistance
+        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_lisp == ''
+            let g:slimv_lisp = input( 'Enter Lisp path (or fill g:slimv_lisp in your vimrc): ', '', 'file' )
+        endif
+        let g:slimv_client = SlimvMakeClientCommand()
     endif
 endfunction
 
 endif
 
 " Name of the REPL buffer inside Vim
-if !exists( 'g:slimv_bufname' )
-    let g:slimv_bufname = 'Slimv.REPL'
+if !exists( 'g:slimv_repl_name' )
+    let g:slimv_repl_name = 'Slimv.REPL'
 endif
 
 
 " Build client command (if not given in vimrc)
 if !exists( 'g:slimv_client' )
-    let g:slimv_client = SlimvClientCommand()
+    let g:slimv_client = SlimvMakeClientCommand()
 endif
 
 " Slimv keybinding set (0 = no keybindings)
 function! SlimvOpenReplBuffer()
     "TODO: check if this works without 'set hidden'
     "TODO: add option for split window
-    let repl_buf = bufnr( g:slimv_bufname )
+    let repl_buf = bufnr( g:slimv_repl_name )
     if repl_buf == -1
         " Create a new REPL buffer
-        exe "edit " . g:slimv_bufname
+        exe "edit " . g:slimv_repl_name
     else
         " REPL buffer is already created. Check if it is open in a window
         let repl_win = bufwinnr( repl_buf )
     return getreg( '"s' )
 endfunction
 
-" Prepare argument list to be sent to the client
-function SlimvMakeArgs( args )
-    let ar = a:args
-    let i = 0
-    while i < len(ar)
-        let ar[i] = substitute( ar[i], '"',  '\\"', 'g' )
-        let i = i + 1
-    endwhile
-    let a = join( ar, '" "' )
-    "let a = substitute( a, '"',  '\\"', 'g' )
-    let a = substitute( a, '\n', '\\n', 'g' )
-    let a = '"' . a . '" '
-    return a
-endfunction
-
-" Send text to the client
-function! SlimvSendToClient( args )
-    if g:slimv_debug_client == 0
-        let result = system( g:slimv_client . ' -c ' . SlimvMakeArgs(a:args) )
-    else
-        execute '!' . g:slimv_client . ' -c ' . SlimvMakeArgs(a:args)
-    endif
-endfunction
-
 " Send argument to Lisp server for evaluation
 function! SlimvEval( args )
-    if g:slimv_client == ''
-        " No command to start client, we are clueless, ask user for assistance
-        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_lisp == ''
-            let g:slimv_lisp = input( 'Enter Lisp path (or fill g:slimv_lisp in your vimrc): ', '', 'file' )
-        endif
-        let g:slimv_client = SlimvClientCommand()
-    endif
-
+    call SlimvClientCommand()
     if g:slimv_client == ''
         return
     endif