Hi. Here is my enhanced script.
Should now work for all windows users with python enabled vim too.
(Haven't tested it yet)

If you don't have any comments I'll add it to vimscripts an vim.org

Marc

============= runinbg.vim ======================================================
" author : Marc Weber
" purpose: run commands in background and continue with your work
" os: 
"   linux with bash or python enabled, 
"   windows with bash or python enabled (not yet tested but should work)

" usage: see RunMakeInBG
" eg call RunMakeInBG('make all')
" or
" eg call RunMakeInBG(['make','all'])

" todo? kill processes on exit?
" handle stderr output with python, too

let s:normal_colorscheme=g:colors_name"
let s:normal_colorscheme="less"
let s:workinbackground_colorscheme="lilac"
let s:use_python_if_availible=1

let s:tempfile=tempname()

if has('gui-running') " FIXME: get vim executable name insteadn (cargs 0)
  let s:vim="gs:vim"
else
  let s:vim="s:vim"
endif
let s:vim="/usr/bin/gvim"

" add your tasks here
fun! BackgroundJobHasStarted()
  exec 'colorscheme '.s:workinbackground_colorscheme
endfun

" add your tasks here
fun! BackgroundJobHasFinisheed(vimPID)
  if len(g:processes)==0
    exec 'colorscheme '.s:normal_colorscheme
  endif
endfun

fun! ProcessFinished(vimPID,status)
  echo 'vimPID '.a:vimPID.' has finished, exit status: '.a:status
  let vimPID = a:vimPID " used for exec commond only (se RunMakeInBG)

  if exists('g:processes["'.a:vimPID.'"]["vimcmd"]')
    echomsg g:processes[a:vimPID]["vimcmd"]
    exec g:processes[a:vimPID]["vimcmd"]
  endif
  let entry = g:processes[a:vimPID]
  if !exists('g:finished_processes')
    let g:finished_processes={}
  endif
  let g:finished_processes[a:vimPID] = remove(g:processes,a:vimPID)
  call BackgroundJobHasFinisheed(entry)
endfun
.
fun! NotifyProcessId(vimProcessId,pid)
  echo 'pid is '.a:pid
  let g:processes[a:vimProcessId]['pid']=a:pid
endfun

fun! RunMakeInBG(command)
  let vimCmdAfter = "exec 'cfile '.g:processes[vimPID]['stdout']"
  let vimPID = NewVimProcessId(a:command, vimCmdAfter)
  call RunCommandInBackground(vimPID)
endfun

fun! BashExprCallingVim(vimcmd)
    return s:vim." --servername \"".v:servername."\" --remote-send 
\"<esc>:".a:vimcmd."<cr>\"" 
endfun

" creates a new vim process id
" it is a dictionary (object) so that you can attach additional info..
" g:processes[vimID]['cmd'] will be executed
" g:processes[vimID]['vimcmd'] will be executed after termination (see
" RunMakeInBG)
" first parameter command to execute (['executable','arg1','arg2',..])
" snd parameter vim continuation command to be executed after the command has
" finished vimPID will be the current vim identifier (see RunMakeInBG as
" example)
fun NewVimProcessId(cmd,...)
  if !exists('g:processes')
    let g:processes = {}
  endif
  if !exists('g:nextVimProcessId')
    let g:nextVimProcessId = 1
  endif
  let g:nextVimProcessId += 1
  let vimPID  = g:nextVimProcessId
  let g:processes[vimPID]={}
  if type(a:cmd) != 3
    " no array, try splitting the argument into executable and args ( FIXME!)
    let cmd = split(a:cmd,' ')
  else
    let cmd = a:cmd
  endif
  let g:processes[vimPID]['cmd'] = cmd
  if a:0>0
    let g:processes[vimPID]['vimcmd']=a:1
  endif
  return vimPID
endfun

fun CommandToSh(cmd)
  let result = []
  for i in a:cmd
    let i = substitute(i,' ','\ ','g')
    let i = substitute(i,'"','\" ','g')
    let result += [i]
  endfor
  return join(result,' ')
endfun


fun! RunCommandInBackground(vimPID)
  if !has('clientserver') 
    echoe "no client-server version"
    return
  endif
  let errorfile = tempname() " not yet implemented
  let outfile = tempname()
  


  let g:processes[a:vimPID]['stdout'] = outfile

  if has('python') && s:use_python_if_availible
    call RunProcessInPythonThread(a:vimPID)
  else
    " let vim now which pid it is (bash $$ substitution
    let shcmd = BashExprCallingVim('call 
NotifyProcessId('.a:vimPID.',"$$")').';'
    " execute the command! :
    let shcmd .= CommandToSh(g:processes[a:vimPID]['cmd']).' &> '.outfile.'; '
    " notify vim that the command! has finished
    let shcmd .= BashExprCallingVim("call 
ProcessFinished('".a:vimPID."',$?)").';'
    let cmdtoexecute='sh -c "'.substitute(shcmd,'"','\\"','g').'" &'
    let g:processes[a:vimPID]['shcmd'] = cmdtoexecute
    call BackgroundJobHasStarted()
    call system(cmdtoexecute)
  endif
endfun

fun! RunProcessInPythonThread(vimPID)
  echo a:vimPID
"exec 'python sys.argv['.a:vimPID.']'
"py << EOF
"vimPID=sys.argv[0]

" if you know a better solution than using g:vimPID than mail me!
let g:vimPID=a:vimPID
let g:use_this_vim = s:vim
py << EOF
vimPID = vim.eval("g:vimPID")
print type(vimPID)
thread=MyThread( vimPID, vim.eval("g:processes['%s']['cmd']"%(vimPID)))
thread.cmd = vim.eval("g:processes['%(vimPID)s']['cmd']"%locals())
thread.stdout  = vim.eval("g:processes[%(vimPID)s]['stdout']"%locals())
thread.vim = vim.eval("g:use_this_vim")
thread.servername = vim.eval("v:servername")
thread.start()
EOF
unlet g:vimPID
unlet g:use_this_vim
endfun

if exists('g:pythonthreadclassinitialized')
  finish
endif
let g:pythonthreadclassinitialized=1
py << EOF
from subprocess import Popen, PIPE
import threading
import os
import vim
class MyThread ( threading.Thread ):
  def __init__(self, vimPID, command):
    threading.Thread.__init__(self)
    self.vimPID=vimPID
    self.command=command

  def run ( self ):
    popenobj  = Popen(self.cmd,stdout=PIPE)
    self.executeVimCommand("call 
NotifyProcessId(%s,%s)"%(self.vimPID,popenobj.pid))
    stdoutwriter = open(self.stdout,'w')
    stdoutwriter.writelines(popenobj.stdout.readlines())
    stdoutwriter.close()
    popenobj.wait()
    self.executeVimCommand("call 
ProcessFinished(%s,%d)"%(self.vimPID,popenobj.returncode))
  def executeVimCommand(self, cmd):
    # can't use vim.command here because vim hasn't been written for multiple
    # threads. I'm getting Xlib: unexpected async reply (sequence 0x859) ;-)
    # will use server commands again
    popenobj = 
Popen([self.vim,"--servername","%s"%(self.servername),"--remote-send","<esc>:%(cmd)s<cr>"%locals()])
    popenobj.wait()

EOF
============= end- =============================================================

Reply via email to