updated on Fri Jan 20 04:00:45 UTC 2012
[aur-mirror.git] / vimsh / vimsh.py
blobc49674688c847fa244dddd5cac104223a80de69b
1 #ls###############################################################################
3 # file: vimsh.py
4 # purpose: allows execution of shell commands in a vim buffer
6 # author: brian m sturk bsturk@adelphia.net,
7 # http://users.adelphia.net/~bsturk
8 # created: 12/02/01
9 # last_mod: 03/26/04
10 # version: 0.20
12 # usage, etc: see vimsh.readme
13 # history: see ChangeLog
14 # in the works: see TODO
16 ###############################################################################
18 import vim, sys, os, string, signal, re, time
20 ## NOTE: If you're having a problem running vimsh, please
21 ## change the 0 to a 1 for _DEBUG_ and send me an email
22 ## of the output.
24 _DEBUG_ = 0
25 _BUFFERS_ = []
27 ################################################################################
29 try:
30 if sys.platform == 'win32':
31 import popen2, stat
32 use_pty = 0
34 else:
35 import pty, tty, select
36 use_pty = 1
38 except ImportError:
39 print 'vimsh: import error'
41 ################################################################################
42 ## class vimsh ##
43 ################################################################################
45 class vimsh:
46 def __init__( self, _sh, _arg, _filename ):
48 self.sh = _sh
49 self.arg = _arg
50 self.filename = _filename
52 self.prompt_line, self.prompt_cursor = self.get_vim_cursor_pos()
54 self.password_regex = [ '^\s*Password:', ## su, ssh, ftp
55 'password:', ## ???, seen this somewhere
56 'Password required' ] ## other ftp clients
58 self.last_cmd_executed = "foobar"
59 self.keyboard_interrupt = 0
60 self.shell_exited = 0
61 self.buffer = vim.current.buffer
63 ################################################################################
65 def setup_pty( self, _use_pty ):
67 self.using_pty = _use_pty
69 if _use_pty:
71 ## The lower this number is the more responsive some commands
72 ## may be ( printing prompt, ls ), but also the quicker others
73 ## may timeout reading their output ( ping, ftp )
75 self.delay = 0.1
77 ## Hack to get pty name until I can figure out to get name
78 ## of slave pty using pty.fork() I've tried everything
79 ## including using all of the python src for pty.fork().
80 ## I'm probably trying to do something I can't do. However,
81 ## there does seem to be a std call named ptsname() which
82 ## returns the slave pty name i.e. /dev/pty/XX
84 ## Assumption is, that between the dummy call to
85 ## master_open is done and the pty.fork happens, we'll be
86 ## the next pty entry after the one from pty.master_open()
87 ## According to SysV docs it will look for the first
88 ## unused, so this shouldn't be too bad besides its looks.
89 ## Only have to make sure they're not already in use and
90 ## if it is try the next one etc.
92 self.master, pty_name = pty.master_open()
93 dbg_print ( 'setup_pty: slave pty name is ' + pty_name )
95 self.pid, self.fd = pty.fork()
97 self.outd = self.fd
98 self.ind = self.fd
99 self.errd = self.fd
101 signal.signal( signal.SIGCHLD, self.sigchld_handler )
103 if self.pid == 0:
105 ## In spawned shell process, NOTE: any 'print'ing done within
106 ## here will corrupt vim.
108 attrs = tty.tcgetattr( 1 )
110 attrs[ 6 ][ tty.VMIN ] = 1
111 attrs[ 6 ][ tty.VTIME ] = 0
112 attrs[ 0 ] = attrs[ 0 ] | tty.BRKINT
113 attrs[ 0 ] = attrs[ 0 ] & tty.IGNBRK
114 attrs[ 3 ] = attrs[ 3 ] & ~tty.ICANON & ~tty.ECHO
116 tty.tcsetattr( 1, tty.TCSANOW, attrs )
118 if self.arg != '':
119 os.execv( self.sh, [ self.sh, self.arg ] )
121 else:
122 os.execv( self.sh, [ self.sh, ] )
124 else:
126 try:
127 attrs = tty.tcgetattr( 1 )
129 termios_keys = attrs[ 6 ]
131 except:
132 dbg_print ( 'setup_pty: tcgetattr failed' )
133 return
135 # Get *real* key-sequence for standard input keys, i.e. EOF
137 self.eof_key = termios_keys[ tty.VEOF ]
138 self.eol_key = termios_keys[ tty.VEOL ]
139 self.erase_key = termios_keys[ tty.VERASE ]
140 self.intr_key = termios_keys[ tty.VINTR ]
141 self.kill_key = termios_keys[ tty.VKILL ]
142 self.susp_key = termios_keys[ tty.VSUSP ]
144 else:
146 ## Use pipes on Win32. not as reliable/nice. works OK but with limitations.
148 self.delay = 0.2
150 try:
151 import win32pipe
153 dbg_print ( 'setup_pty: using windows extensions' )
154 self.stdin, self.stdout, self.stderr = win32pipe.popen3( self.sh + " " + self.arg )
156 except ImportError:
158 dbg_print ( 'setup_pty: not using windows extensions' )
159 self.stdout, self.stdin, self.stderr = popen2.popen3( self.sh + " " + self.arg, -1, 'b' )
161 self.outd = self.stdout.fileno()
162 self.ind = self.stdin.fileno ()
163 self.errd = self.stderr.fileno()
165 self.intr_key = '\x03'
166 self.eof_key = '\x04'
168 ################################################################################
170 def execute_cmd( self, _cmd = None, _null_terminate = 1 ):
172 dbg_print ( 'execute_cmd: Entered cmd is ' + str( _cmd ) )
174 if self.keyboard_interrupt:
175 dbg_print( 'execute_cmd: keyboard interrupt earlier, cleaning up' )
177 self.page_output( 1 )
178 self.keyboard_interrupt = 0
180 return
182 ## This is the main worker function
184 try:
185 print "" ## Clears the ex command window
187 cur = self.buffer
188 cur_line, cur_row = self.get_vim_cursor_pos()
190 if _cmd == None:
192 ## Grab everything from the prompt to the current cursor position.
194 _cmd = cur[ self.prompt_line - 1 : cur_line ] # whole line
195 _cmd[0] = _cmd[0][ ( self.prompt_cursor - 1 ) : ] # remove prompt, zero based slicing
197 if re.search( r'^\s*\bclear\b', _cmd[0] ) or re.search( r'^\s*\bcls\b', _cmd[0] ):
199 dbg_print ( 'execute_cmd: clear detected' )
200 self.clear_screen( True )
202 elif re.search( r'^\s*\exit\b', _cmd[0] ):
204 dbg_print ( 'execute_cmd: exit detected' )
205 self.handle_exit_cmd( _cmd )
207 else:
209 dbg_print ( 'execute_cmd: other command executed' )
211 for c in _cmd:
212 if _null_terminate:
213 self.write( c + '\n' )
215 else:
216 self.write( c )
218 self.end_exe_line()
219 vim.command( "startinsert!" )
221 self.last_cmd_executed = _cmd[0]
223 except KeyboardInterrupt:
225 dbg_print( 'execute_cmd: in keyboard interrupt exception, sending SIGINT' )
227 self.keyboard_interrupt = 1
229 ## TODO: Sending Ctrl-C isn't working on Windows yet, so
230 ## executing something like 'findstr foo' will hang.
232 if sys.platform != 'win32':
233 self.send_intr()
235 ################################################################################
237 def end_exe_line( self ):
239 ## read anything that's on stdout after a command is executed
241 dbg_print( 'end_exe_line: enter' )
243 cur = self.buffer
245 cur.append( "" )
246 vim.command( "normal G$" )
248 self.read( cur )
249 self.check_for_passwd()
251 ################################################################################
253 def write( self, _cmd ):
255 dbg_print( 'write: writing out --> ' + _cmd )
257 os.write( self.ind, _cmd )
259 ################################################################################
261 def read( self, _buffer ):
263 num_iterations = 0 ## counter for periodic redraw
264 iters_before_redraw = 10
265 any_lines_read = 0 ## sentinel for reading anything at all
267 if sys.platform == 'win32':
268 iters_before_redraw = 1
270 while 1:
271 if self.using_pty:
272 r, w, e = select.select( [ self.outd ], [], [], self.delay )
274 else:
275 r = [1,] ## pipes, unused, fake it out so I don't have to special case
277 for file_iter in r:
279 lines = ''
281 if self.using_pty:
282 lines = os.read( self.outd, 32 )
284 else:
285 lines = self.pipe_read( self.outd, 2048 )
287 if lines == '':
288 dbg_print( 'read: No more data on stdout pipe_read' )
290 r = [] ## sentinel, end of data to read
291 break
293 any_lines_read = 1
294 num_iterations += 1
296 lines = self.process_read( lines )
297 self.print_lines( lines, _buffer )
299 ## Give vim a little cpu time, so programs that spit
300 ## output or are long operations seem more responsive
302 if not num_iterations % iters_before_redraw:
303 dbg_print( 'read: Letting vim redraw' )
304 vim.command( 'call VimShRedraw()' )
306 if r == []:
307 dbg_print( 'read: end of data to self.read()' )
308 self.end_read( any_lines_read )
310 break
312 ################################################################################
314 def process_read( self, _lines ):
316 dbg_print( 'process_read: Raw lines read from stdout:' )
317 dbg_print( _lines )
319 lines_to_print = string.split( _lines, '\n' )
321 ## On windows cmd is "echoed" and output sometimes has leading empty line
323 if sys.platform == 'win32':
324 m = re.search( re.escape( self.last_cmd_executed.strip() ), lines_to_print[ 0 ] )
326 if m != None or lines_to_print[ 0 ] == "":
327 dbg_print( 'process_read: Win32, removing leading blank line' )
328 lines_to_print = lines_to_print[ 1: ]
330 num_lines = len( lines_to_print )
332 ## Split on '\n' sometimes returns n + 1 entries
334 if num_lines > 1:
335 last_line = lines_to_print[ num_lines - 1 ].strip()
337 if last_line == "":
338 lines_to_print = lines_to_print[ :-1 ]
340 errors = self.chk_stderr()
342 if errors:
343 dbg_print( 'process_read: Prepending stderr --> ' )
344 lines_to_print = errors + lines_to_print
346 return lines_to_print
348 ################################################################################
350 def print_lines( self, _lines, _buffer ):
352 num_lines = len( _lines )
354 dbg_print( 'print_lines: Number of lines to print--> ' + str( num_lines ) )
356 for line_iter in _lines:
358 dbg_print( 'print_lines: Current line is --> %s' % line_iter )
360 m = None
362 while re.search( '\r$', line_iter ):
364 dbg_print( 'print_lines: removing trailing ^M' )
366 line_iter = line_iter[ :-1 ] # Force it
367 m = True
369 ## Jump to the position of the last insertion to the buffer
370 ## if it was a new line it should be 1, if it wasn't
371 ## terminated by a '\n' it should be the end of the string
373 vim.command( "normal " + str( self.prompt_cursor ) + "|" )
375 cur_line, cur_row = self.get_vim_cursor_pos()
376 dbg_print( 'print_lines: After jumping to end of last cmd: line %d row %d' % ( cur_line, cur_row ) )
378 dbg_print( 'print_lines: Pasting ' + line_iter + ' to current line' )
379 _buffer[ cur_line - 1 ] += line_iter
381 ## If there's a '\n' or using pipes and it's not the last line
383 if not self.using_pty or m != None:
385 dbg_print( 'print_lines: Appending new line since ^M or not using pty' )
386 _buffer.append( "" )
388 vim.command( "normal G$" )
389 vim.command( "startinsert!" )
391 self.prompt_line, self.prompt_cursor = self.get_vim_cursor_pos()
392 dbg_print( 'print_lines: Saving cursor location: line %d row %d ' % ( self.prompt_line, self.prompt_cursor ) )
394 ################################################################################
396 def end_read( self, any_lines_read ):
398 cur_line, cur_row = self.get_vim_cursor_pos( )
400 if not self.using_pty and any_lines_read:
402 ## remove last line for last read only if lines were
403 ## read from stdout. TODO: any better way to do this?
405 vim.command( 'normal dd' )
407 vim.command( "normal G$" )
408 vim.command( "startinsert!" )
410 ## Tuck away location, all data read is in buffer
412 self.prompt_line, self.prompt_cursor = self.get_vim_cursor_pos()
413 dbg_print( 'end_read: Saving cursor location: line %d row %d ' % ( self.prompt_line, self.prompt_cursor ) )
415 ################################################################################
417 def page_output( self, _add_new_line = 0 ):
419 dbg_print( 'page_output: enter' )
421 ## read anything that's left on stdout
423 cur = self.buffer
425 if _add_new_line:
427 cur.append( "" )
428 vim.command( "normal G$" )
430 self.read( cur )
432 self.check_for_passwd()
434 vim.command( "startinsert!" )
436 ################################################################################
438 def cleanup( self ):
440 # NOTE: Only called via autocommand
442 dbg_print( 'cleanup: enter' )
444 # Remove autocommand so we don't get multiple calls
446 vim.command( 'au! BufDelete ' + self.filename )
448 remove_buf( self.filename )
450 if self.shell_exited:
451 dbg_print( 'cleanup: process is already dead, nothing to do' )
452 return
454 try:
456 if not self.using_pty:
457 os.close( self.ind )
458 os.close( self.outd )
460 os.close( self.errd ) ## all the same if pty
462 if self.using_pty:
463 os.kill( self.pid, signal.SIGKILL )
465 except:
466 dbg_print( 'cleanup: Exception, process probably already killed' )
468 ################################################################################
470 def send_intr( self ):
472 dbg_print( 'send_intr: enter' )
474 if show_workaround_msgs == '1':
475 print 'If you do NOT see a prompt in the vimsh buffer, press F5 or go into insert mode and press Enter'
476 print 'If you need a new prompt press F4'
477 print 'NOTE: To disable this help message set \'g:vimsh_show_workaround_msgs\' to 0 in your .vimrc'
479 ## This triggers another KeyboardInterrupt async
481 try:
482 dbg_print( 'send_intr: writing intr_key' )
483 self.write( self.intr_key )
485 self.page_output( 1 )
487 except KeyboardInterrupt:
489 dbg_print( 'send_intr: caught KeyboardInterrupt in send_intr' )
490 pass
492 ################################################################################
494 def send_eof( self ):
496 dbg_print( 'send_eof: enter' )
498 try: ## could cause shell to exit
500 self.write( self.eof_key )
501 self.page_output( 1 )
503 except Exception, e:
505 dbg_print( 'send_eof: exception' )
507 ## shell exited, self.shell_exited may not have been set yet in
508 ## sigchld_handler.
510 dbg_print( 'send_eof: shell_exited is ' + str( self.shell_exited ) )
512 self.exit_shell()
514 ################################################################################
516 def handle_exit_cmd( self, _cmd ):
518 ## Exit was typed, could be the spawned shell, or a subprocess like
519 ## telnet/ssh/etc.
521 dbg_print( 'handle_exit_cmd: enter' )
523 if not self.shell_exited: ## process is still around
525 try: ## could cause shell to exit
527 dbg_print ( 'handle_exit_cmd: shell is still around, writing exit command' )
528 self.write( _cmd[0] + '\n' )
530 self.end_exe_line()
531 vim.command( "startinsert!" )
533 except Exception, e:
535 dbg_print( 'handle_exit_cmd: exception' )
537 ## shell exited, self.shell_exited may not have been set yet in
538 ## sigchld_handler.
540 dbg_print( 'handle_exit_cmd: shell_exited is ' + str( self.shell_exited ) )
542 self.exit_shell()
544 ################################################################################
546 def exit_shell( self ):
548 dbg_print( 'exit_shell: enter' )
550 ## when exiting this way can't have the autocommand
551 ## for BufDelete run. It crashes vim. TODO: Figure this out.
553 vim.command( 'stopinsert' )
554 vim.command( 'au! BufDelete ' + self.filename )
555 vim.command( 'bdelete! ' + self.filename )
557 remove_buf( self.filename )
559 ################################################################################
561 def sigchld_handler( self, sig, frame ):
563 dbg_print( 'sigchld_handler: caught SIGCHLD' )
565 self.waitpid()
567 ################################################################################
569 def sigint_handler( self, sig, frame ):
571 dbg_print( 'sigint_handler: caught SIGINT' )
572 dbg_print( '' )
574 self.waitpid()
576 ################################################################################
578 def waitpid( self ):
580 ## This routine cannot do anything except for marking that the original
581 ## shell process has gone away if it has. This is due to the async
582 ## nature of signals.
584 if os.waitpid( self.pid, os.WNOHANG )[0]:
586 self.shell_exited = 1
587 dbg_print( 'waitpid: shell exited' )
589 else:
591 dbg_print( 'waitpid: shell hasn\'t exited, ignoring' )
593 ################################################################################
595 def set_timeout( self ):
597 timeout_ok = 0
599 while not timeout_ok:
601 try:
602 vim.command( 'let timeout = input( "Enter new timeout in seconds (i.e. 0.1), currently set to ' + str( self.delay ) + ' : " )' )
604 except KeyboardInterrupt:
605 return
607 timeout = vim.eval( "timeout" )
609 if timeout == "": ## usr cancelled dialog, break out
610 timeout_ok = 1
612 else:
613 timeout = float( timeout )
615 if timeout >= 0.1:
616 print ' ---> New timeout is ' + str( timeout ) + ' seconds'
617 self.delay = timeout
618 timeout_ok = 1
620 ################################################################################
622 def clear_screen( self, in_insert_mode ):
624 dbg_print( 'clear_screen: insert mode is ' + str( in_insert_mode ) )
626 self.write( "" + "\n" ) ## new prompt
628 if clear_all == '1':
629 vim.command( "normal ggdG" )
631 self.end_exe_line()
633 if clear_all == '0':
634 vim.command( "normal zt" )
636 if in_insert_mode:
637 vim.command( "startinsert!" )
639 else:
640 vim.command( 'stopinsert' )
642 ################################################################################
644 def new_prompt( self ):
646 self.execute_cmd( [""] ) # just press enter
648 vim.command( "normal G$" )
649 vim.command( "startinsert!" )
651 ################################################################################
653 def get_vim_cursor_pos( self ):
655 cur_line, cur_row = vim.current.window.cursor
657 return cur_line, cur_row + 1
659 ################################################################################
661 def check_for_passwd( self ):
663 cur_line, cur_row = self.get_vim_cursor_pos()
665 prev_line = self.buffer[ cur_line - 1 ]
667 for regex in self.password_regex:
669 if re.search( regex, prev_line ):
671 try:
672 vim.command( 'let password = inputsecret( "Password? " )' )
674 except KeyboardInterrupt:
675 return
677 password = vim.eval( "password" )
679 self.execute_cmd( [password] ) ## recursive call here...
681 ################################################################################
683 def pipe_read( self, pipe, minimum_to_read ):
685 ## Hackaround since Windows doesn't support select() except for sockets.
687 dbg_print( 'pipe_read: minimum to read is ' + str( minimum_to_read ) )
688 dbg_print( 'pipe_read: sleeping for ' + str( self.delay ) + ' seconds' )
690 time.sleep( self.delay )
692 count = 0
693 count = os.fstat( pipe )[stat.ST_SIZE]
695 data = ''
697 dbg_print( 'pipe_read: initial count via fstat is ' + str( count ) )
699 while ( count > 0 ):
701 tmp = os.read( pipe, 1 )
702 data += tmp
704 count = os.fstat( pipe )[stat.ST_SIZE]
706 if len( tmp ) == 0:
707 dbg_print( 'pipe_read: count ' + str( count ) + ' but nothing read' )
708 break
710 ## Be sure to break the read, if asked to do so,
711 ## after we've read in a line termination.
713 if minimum_to_read != 0 and len( data ) > 0 and data[ len( data ) -1 ] == '\n':
715 if len( data ) >= minimum_to_read:
716 dbg_print( 'pipe_read: found termination and read at least the minimum asked for' )
717 break
719 else:
720 dbg_print( 'pipe_read: not all of the data has been read: count is ' + str( count ) )
722 dbg_print( 'pipe_read: returning' )
724 return data
726 ################################################################################
728 def chk_stderr( self ):
730 errors = ''
731 dbg_print( 'chk_stderr: enter' )
733 if sys.platform == 'win32':
735 err_txt = self.pipe_read( self.errd, 0 )
736 errors = string.split( err_txt, '\n' )
738 num_lines = len( errors )
739 dbg_print( 'chk_stderr: Number of error lines is ' + `num_lines` )
741 last_line = errors[ num_lines - 1 ].strip()
743 if last_line == "":
744 dbg_print( 'chk_stderr: Removing last line, it\'s empty' )
745 errors = errors[ :-1 ]
747 return errors
749 ################################################################################
751 #def thread_worker( self ):
753 #self.idle = 0
754 ## Not working 100% yet
755 #thread.start_new_thread( self.thread_worker, () )
757 #try:
758 #while 1:
760 #time.sleep( 5.0 )
762 ## This doesn't seem to work
763 ## vim.command( 'let dummy = remote_send( v:servername, "<C-\><C-N>:python periodic( \'' + self.filename + '\' )<CR>" )' )
765 ## Nor this
766 #vim.command( 'let dummy = v:servername' )
767 #servername = vim.eval( "dummy" )
768 #os.system( 'gvim --remote-send --servername ' + servername + '"<C-\><C-N>:python periodic( ' + self.filename + ')<CR>"' )
770 ## or this
771 # os.system( 'gvim --remote-expr ":python periodic( \'' + self.filename + '\' )<CR>"' )
773 ## This works well so far ( haven't testing thoroughly though )
774 ## only problem is it changes to normal mode while the user may
775 ## be typing.
777 #os.system( 'gvim --remote-send "<C-\><C-N>:python periodic( \'' + self.filename + '\' )<CR>"' )
779 #except:
780 #pass
782 ################################################################################
783 ## Helper functions ##
784 ################################################################################
786 def test_and_set( vim_var, default_val ):
788 ret = default_val
790 vim.command( 'let dummy = exists( "' + vim_var + '" )' )
791 exists = vim.eval( "dummy" )
793 ## exists will always be a string representation of the evaluation
795 if exists != '0':
796 ret = vim.eval( vim_var )
797 dbg_print( 'test_and_set: variable ' + vim_var + ' exists, using supplied ' + ret )
799 else:
800 dbg_print( 'test_and_set: variable ' + vim_var + ' doesn\'t exist, using default ' + ret )
802 return ret
804 ################################################################################
806 def dump_str_as_hex( _str ):
808 hex_str = ''
810 print 'length of string is ' + str( len( _str ) )
812 for x in range( 0, len( _str ) ):
813 hex_str = hex_str + hex( ord( _str[x] ) ) + "\n"
815 print 'raw line ( hex ) is:'
816 print hex_str
818 ################################################################################
820 def dbg_print( _str ):
822 if _DEBUG_:
823 print _str
825 ################################################################################
827 def new_buf( _filename ):
829 ## If a buffer named vimsh doesn't exist create it, if it
830 ## does, switch to it. Use the config options for splitting etc.
832 filename = _filename
834 try:
835 vim.command( 'let dummy = buflisted( "' + filename + '" )' )
836 exists = vim.eval( "dummy" )
838 if exists == '0':
839 dbg_print( 'new_buf: buffer ' + filename + ' doesn\'t exist' )
841 if split_open == '0':
842 vim.command( 'edit ' + filename )
844 else:
845 vim.command( 'new ' + filename )
847 vim.command( 'setlocal buftype=nofile' )
848 vim.command( 'setlocal bufhidden=hide' )
849 vim.command( 'setlocal noswapfile' )
850 vim.command( 'setlocal tabstop=4' )
851 vim.command( 'setlocal modifiable' )
852 vim.command( 'setlocal nowrap' )
853 vim.command( 'setlocal textwidth=999' )
854 vim.command( 'setfiletype vim_shell' )
856 vim.command( 'au BufDelete ' + filename + ' :python lookup_buf( "' + filename + '" ).cleanup()' )
858 vim.command( 'inoremap <buffer> <CR> <ESC>:python lookup_buf( "' + filename + '" ).execute_cmd()<CR>' )
860 vim.command( 'inoremap <buffer> ' + timeout_key + ' <ESC>:python lookup_buf( "' + filename + '" ).set_timeout()<CR>' )
861 vim.command( 'nnoremap <buffer> ' + timeout_key + ' :python lookup_buf( "' + filename + '" ).set_timeout()<CR>' )
863 vim.command( 'inoremap <buffer> ' + new_prompt_key + ' <ESC>:python lookup_buf ( "' + filename + '" ).new_prompt()<CR>' )
864 vim.command( 'nnoremap <buffer> ' + new_prompt_key + ' :python lookup_buf( "' + filename + '" ).new_prompt()<CR>' )
866 vim.command( 'inoremap <buffer> ' + page_output_key + ' <ESC>:python lookup_buf ( "' + filename + '" ).page_output()<CR>' )
867 vim.command( 'nnoremap <buffer> ' + page_output_key + ' :python lookup_buf( "' + filename + '" ).page_output()<CR>' )
869 vim.command( 'inoremap <buffer> ' + eof_signal_key + ' <ESC>:python lookup_buf ( "' + filename + '" ).send_eof()<CR>' )
870 vim.command( 'nnoremap <buffer> ' + eof_signal_key + ' :python lookup_buf( "' + filename + '" ).send_eof()<CR>' )
872 vim.command( 'inoremap <buffer> ' + intr_signal_key + ' <ESC>:python lookup_buf ( "' + filename + '" ).send_intr()<CR>' )
873 vim.command( 'nnoremap <buffer> ' + intr_signal_key + ' :python lookup_buf( "' + filename + '" ).send_intr()<CR>' )
875 vim.command( 'inoremap <buffer> ' + clear_key + ' <ESC>:python lookup_buf ( "' + filename + '" ).clear_screen( True )<CR>')
876 vim.command( 'nnoremap <buffer> ' + clear_key + ' :python lookup_buf( "' + filename + '").clear_screen( False )<CR>' )
878 return 0
880 else:
882 dbg_print( 'new_buf: file ' + filename + ' exists' )
884 vim.command( "edit " + filename )
885 return 1
887 except:
888 dbg_print( 'new_buf: exception!' + str( sys.exc_info()[0] ) )
890 ################################################################################
892 def spawn_buf( _filename ):
894 exists = new_buf( _filename )
896 if not exists:
898 dbg_print( 'spawn_buf: buffer doesn\'t exist so creating a new one' )
900 cur = vim.current.buffer
902 ## Make vimsh associate buffer with _filename and add to list of buffers
903 vim_shell = vimsh( sh, arg, _filename )
905 _BUFFERS_.append( ( _filename, vim_shell ) )
906 vim_shell.setup_pty( use_pty )
908 vim_shell.read( cur )
909 cur_line, cur_row = vim_shell.get_vim_cursor_pos()
911 ## last line *should* be prompt, tuck it away for syntax hilighting
912 hi_prompt = cur[ cur_line - 1 ]
914 else:
916 dbg_print( 'main: buffer does exist' )
917 vim.command( "normal G$" )
918 vim_shell = lookup_buf( _filename )
920 vim.command( "startinsert!" )
922 ################################################################################
924 def periodic( _filename ):
926 print( 'periodic: enter for ' + _filename )
927 print( 'testing' )
929 if not use_pty:
930 return
932 vim_shell = lookup_buf( _filename )
934 if vim_shell == None:
935 dbg_print( 'periodic: couldn\'t find buffer' )
936 return
938 if vim_shell.idle:
940 try:
941 r, w, e = select.select( [ vim_shell.outd ], [], [], 0.1 )
943 if r == []:
944 return
946 dbg_print( 'periodic: new data to read on pty' )
948 vim_shell.page_output()
950 except:
951 pass
953 ################################################################################
955 def lookup_buf( _filename ):
957 for key, val in _BUFFERS_:
959 if key == _filename:
961 dbg_print( 'lookup_buf: found match ' + str( val ) )
962 return val
964 dbg_print( 'lookup_buf: couldn\'t find match for ' + _filename )
966 return None
968 ################################################################################
970 def remove_buf( _filename ):
972 dbg_print ( 'remove_buf: looking for ' + _filename + ' to remove from buffer list' )
974 idx = 0
976 for key, val in _BUFFERS_:
978 if key == _filename:
979 break
981 idx = idx + 1
983 if ( len( _BUFFERS_ ) >= idx ) & ( len( _BUFFERS_ ) != 0 ):
985 dbg_print ( 'remove_buf: removing buffer from list' )
986 del _BUFFERS_[ idx ]
988 ############################# customization ###################################
990 # Don't edit the lines below, instead set the g:<variable> in your
991 # .vimrc to the value you would like to use. For numeric settings
992 # *DO NOT* put quotes around them. The quotes are only needed in
993 # this script. See vimsh.readme for more details
995 ###############################################################################
997 ## Allow pty prompt override, useful if you have an ansi prompt, etc
1000 prompt_override = int( test_and_set( "g:vimsh_pty_prompt_override", "1" ) )
1002 ## Prompt override, used for pty enabled. Just use a very simple prompt
1003 ## and make no definitive assumption about the shell being used if
1004 ## vimsh_prompt_pty is not set. This will only be used if
1005 ## vimsh_pty_prompt_override (above) is 1.
1007 ## NOTE: [t]csh doesn't use an environment variable for setting the prompt so setting
1008 ## an override prompt will not work.
1011 if use_pty:
1012 if prompt_override:
1013 new_prompt = test_and_set( 'g:vimsh_prompt_pty', r'> ' )
1015 os.environ['prompt'] = new_prompt
1016 os.environ['PROMPT'] = new_prompt
1017 os.environ['PS1'] = new_prompt
1019 ## shell program and supplemental arg to shell. If no supplemental
1020 ## arg, just use ''
1023 if sys.platform == 'win32':
1024 sh = test_and_set( 'g:vimsh_sh', 'cmd.exe' ) # NT/Win2k
1025 arg = test_and_set( 'g:vimsh_sh_arg', '-i' )
1027 else:
1028 sh = test_and_set( 'g:vimsh_sh', '/bin/sh' ) # Unix
1029 arg = test_and_set( 'g:vimsh_sh_arg', '-i' )
1031 ## clear shell command behavior
1032 # 0 just scroll for empty screen
1033 # 1 delete contents of buffer
1036 clear_all = test_and_set( "g:vimsh_clear_all", "0" )
1038 ## new vimsh window behavior
1039 # 0 use current buffer if not modified
1040 # 1 always split
1043 split_open = test_and_set( "g:vimsh_split_open", "1" )
1045 ## show helpful (hopefully) messages, mostly for issues that aren't resolved but
1046 ## have workarounds
1047 # 0 don't show them, you know what your doing
1048 # 1 show them
1051 show_workaround_msgs = test_and_set( "g:vimsh_show_workaround_msgs", "1" )
1053 ## Prompts for the timeouts for read( s )
1055 # set low for local usage, higher for network apps over slower link
1056 # 0.1 sec is the lowest setting
1057 # over a slow link ( 28.8 ) 1+ seconds works well
1060 timeout_key = test_and_set( "g:vimsh_timeout_key", "<F3>" )
1062 ## Create a new prompt at the bottom of the buffer, useful if stuck.
1063 ## Please try to give me a bug report of how you got stuck if possible.
1065 new_prompt_key = test_and_set( "g:vimsh_new_prompt_key", "<F4>" )
1067 ## If output just stops, could be because of short timeouts, allow a key
1068 ## to attempt to read more, rather than sending the <CR> which keeps
1069 ## spitting out prompts.
1071 page_output_key = test_and_set( "g:vimsh_page_output_key", "<F5>" )
1073 ## Send a process SIGINT (INTR) (usually control-C)
1075 intr_signal_key = test_and_set( "g:vimsh_intr_key", "<C-c>" )
1077 ## Send a process EOF (usually control-D) python needs it to
1078 ## quit interactive shell.
1080 eof_signal_key = test_and_set( "g:vimsh_eof_key", "<C-d>" )
1082 ## Clear screen
1084 clear_key = test_and_set( "g:vimsh_clear_key", "<C-l>" )
1086 ############################ end customization #################################