Vim Tips Wiki
Advertisement
Tip 1549 Printable Monobook Previous Next

created March 20, 2008 · complexity basic · author Don Reba · version 7.0


Under Windows, Vim provides two commands for running external programs: ! and !start. The first suspends Vim, runs the program, waits for a keypress, then returns to Vim. The second runs the program without suspending Vim or waiting for a keypress.

The first method has the drawback of not letting you work while the program is running, but with the second you do not see the result of the program's execution. Here is how to get the best of both worlds:

:!start cmd /c "my app.exe" & pause

Following is an alternative (close the command prompt window when wanted):

:!start cmd /k "my app.exe"

The following mapping allows you to press F5 to run the compiled program corresponding to the current source file:

:nnoremap <silent> <buffer> <F5> :!start cmd /c "%<.exe" & pause<CR>

Explanation

This tip assumes that cmd.exe is your shell (Windows command prompt :help 'shell'), and that you are running a console program (not GUI). If you enter a command like :!calc (to run calc.exe for the Windows calculator), Vim will open a shell window, then run calc from that shell. When calc is closed, the prompt Hit any key to close this window... appears, and Vim is frozen until a key is pressed. Calculator is a GUI program so it runs in a new process, and in a new window. If you run a console program (for example, a batch file), the shell process and window are used.

Under Windows, if the Vim command begins with "!start ", Vim creates a process to run the program without invoking a shell, so the "Hit any key to close this window..." message does not appear. :help :!start :help win32-vimrun

If you want to asynchronously run a GUI program like Calculator, you can simply enter:

:!start calc

!start vs. Windows start command

The following mapping launches the currently edited file with the external application that is associated with it, using the file type's default handler. This is like entering the filename in the Start > Run... dialog, or double-clicking in Windows Explorer. For example, example.html will be opened in your default browser.

:nmap <Leader>x :silent ! start "1" "%:p"<CR>

Explanation

In the Vim command, ':silent' avoids the Hit-Enter prompt, ':p' makes this launch independent from the CWD, the surrounding "" make it handle spaces. The Windows start command opens the passed file in a separate window, so that Vim doesn't block; the Windows shell locates the application that is associated with the type of file. The "1" is the optional "title" argument to 'start'; without this dummy, 'start' will take the passed file as the title, because it is enclosed in double quotes.

See also

Comments

Is there a way to do this on Linux or Mac OS? Thanks!


Here is an example of getting the asynchronous process to communicate back to Vim. The following will perform a grep (well, a findstr) asynchronously on Windows:

if has('win32')
  command! -bar -complete=file -nargs=+ GrepAsync call AsyncGrep('',<f-args>)
  command! -bar -complete=file -nargs=+ RGrepAsync call AsyncGrep('/R',<f-args>)

  function! AsyncGrep(flags, pattern, ...)
    let s:grep_temp_file = tempname()
    exec 'silent !start cmd /c "findstr /n '.a:flags.' "'.a:pattern.'" "'.substitute(join(a:000, '" "'),'/','\','g').'" > "'.s:grep_temp_file.'"'
          \ ' && vim --servername '.v:servername.' --remote-expr "ParseAsyncGrep('."'".s:grep_temp_file."')".'""'
  endfunction

  function! ParseAsyncGrep(tempfile)
    " the echomsg is mostly debug, but could be used instead of the botright copen to alert the user without interfering
    echomsg "got grep file ".a:tempfile

    " set up the errorformat so Vim can parse the output
    let oldefm = &errorformat
    let &errorformat = &grepformat

    " parse the results into the quickfix window, but don't jump to the first search hit
    exec 'cgetfile '.a:tempfile

    " restore the previous state
    let &errorformat = oldefm
    call delete(a:tempfile)

    " open the quickfix window but don't interfere with the user
    botright copen    " this might get annoying for some users
    wincmd p " we just opened the quickfix window which could interrupt what the user is doing, go back so we don't interfere
    redraw " I had some funny issues where the quickfix window was there, but not visible without this command
  endfunction
endif

We should point out the use of v:servername with --servername, and the use of --remote-expr with a function defined for the purpose.

This does steal focus from Vim while the command is running, but Vim is not waiting on the process to complete, so you can continue working.

Do we need a simpler example?

--Fritzophrenic 17:31, January 27, 2010 (UTC)

Advertisement