How to execute file I'm editing in Vi(m)

VimExec

Vim Problem Overview


How to execute file that I'm editing in Vi(m) and get output in split window (like in SciTE)?

Of course I could execute it like that:

:!scriptname

But is it posible to avoid writing script name and how to get output in split window instead just bottom of the screen?

Vim Solutions


Solution 1 - Vim

There is the make command. It runs the command set in the makeprg option. Use % as a placeholder for the current file name. For example, if you were editing a python script:

:set makeprg=python\ %

Yes, you need to escape the space. After this you can simply run:

:make

If you wish, you can set the autowrite option and it will save automatically before running the makeprg:

:set autowrite

This solves the execute part. Don't know any way of getting that output into a split window that doesn't involve redirection to file.

Solution 2 - Vim

To access the current buffer's filename, use %. To get it into a variable you can use the expand() function. To open a new window with a new buffer, use :new or :vnew. To pipe the output from a command into the current buffer, use :.! . Putting it all together:

:let f=expand("%")|vnew|execute '.!ruby "' . f . '"'

obviously replacing ruby with whatever command you want. I used execute so I could surround the filename with quotation marks, so it'll work if the filename has spaces in it.

Solution 3 - Vim

Vim has ! ("bang") command which executes shell command directly from VIM window. Moreover it allows launching sequence of commands that are connected with pipe and read stdout.

For example:

! node %

is equivalent to opening command prompt window and launching commands:

cd my_current_directory 
node my_current_file

See "Vim tips: Working with external commands" for details.

Solution 4 - Vim

I have a shortcut for that in my vimrc:

nmap <F6> :w<CR>:silent !chmod 755 %<CR>:silent !./% > .tmp.xyz<CR>
     \ :tabnew<CR>:r .tmp.xyz<CR>:silent !rm .tmp.xyz<CR>:redraw!<CR>

This writes the current buffer, makes the current file executable (unix only), executes it (unix only) and redirects the output to .tmp.xyz, then creates a new tab, reads the file and then deletes it.

Breaking it down:

:w<CR>                             write current buffer
:silent !chmod 755 %<CR>           make file executable
:silent !./% > .tmp.xyz<CR>        execute file, redirect output
:tabnew<CR>                        new tab
:r .tmp.xyz<CR>                    read file in new tab
:silent !rm .tmp.xyz<CR>           remove file
:redraw!<CR>                       in terminal mode, vim get scrambled
                                   this fixes it

Solution 5 - Vim

For Shell script I've used

:set makeprg=%

:make

Solution 6 - Vim

Vim 8 has an interactive terminal built in. To run the current bash script in a split pane:

:terminal bash %

or for short

:ter bash %

% expands to the current file name.

From :help terminal:

The terminal feature is optional, use this to check if your Vim has it:
    echo has('terminal')
If the result is "1" you have it.

Solution 7 - Vim

I use a slightly more intrusive mechanism through maps:

map ;e :w<CR>:exe ":!python " . getreg("%") . "" <CR>

Just makes it so I don't have to save, then go. Just go.

Solution 8 - Vim

You can use vim's plugin bexec. To my knowledge the latest version is 0.5.

Then:

$ mkdir -p ~/.vim/plugin
$ mv bexec-0.5.vba ~/.vim/plugin
$ vim ~/.vim/plugin/bexec-0.5.vba

Inside vim itself while editing the .vba file do:

:so %

Some output will show up letting you know that bexec.vim has been written as well as documentation, etc..

Now, you can test it by opening your (whatever language script that has an #! interpreter working properly) in vim and run

:Bexec 

Note: I wanted the split to be vertical rather than horizontal, so I did:

$ grep -i -n split ~/.vim/plugin/bexec.vim | grep -i hor
102:    let bexec_splitdir = "hor" " hor|ver
261:        exec {"ver":"vsp", "hor":"sp"}[g:bexec_splitdir]

and changed the value of from "hor" to "ver"..

I know it's an old question, but I hope this can help someone out there. I have been running in the same issue while taking Coursera's Startup Engineering course where professor Palaji uses Emacs and I don't like Emacs..

Solution 9 - Vim

Based on @SethKriticos and @Cyril answers I now use the following:

function! Setup_ExecNDisplay()
  execute "w"
  execute "silent !chmod +x %:p"
  let n=expand('%:t')
  execute "silent !%:p 2>&1 | tee ~/.vim/output_".n
  " I prefer vsplit
  "execute "split ~/.vim/output_".n
  execute "vsplit ~/.vim/output_".n
  execute "redraw!"
  set autoread
endfunction

function! ExecNDisplay()
  execute "w"
  let n=expand('%:t')
  execute "silent !%:p 2>&1 | tee ~/.vim/output_".n
  " I use set autoread
  "execute "1 . 'wincmd e'"
endfunction

:nmap <F9> :call Setup_ExecNDisplay()<CR>
:nmap <F2> :call ExecNDisplay()<CR>

Use F9 to setup the new window and F2 to execute your script and tee to your output file.

I also added the script name to the output file name, so that you can use this for multiple scripts at the same time.

Solution 10 - Vim

@xorpaul

I was looking for this script (python/Windows) for quite some time. As there is no "tee" in Windows I changed it to:

function! Setup_ExecNDisplay()
  execute "w"
  let n=expand('%:t')
  execute "silent ! python % > d:\\temp\\output_".n ." 2>&1"
  execute "vsplit d:\\temp\\output_".n
  execute "redraw!"
  set autoread
endfunction

function! ExecNDisplay()
  execute "w"
  let n=expand('%:t')
  execute "silent ! python % > d:\\temp\\output_".n . " 2>&1"
endfunction

:nmap <F9> :call Setup_ExecNDisplay()<CR>
:nmap <F2> :call ExecNDisplay()<CR>

Solution 11 - Vim

In your .vimrc you can paste this function

function! s:ExecuteInShell(command)
  let command = join(map(split(a:command), 'expand(v:val)'))
  let winnr = bufwinnr('^' . command . '$')
  silent! execute ':w'
  silent! execute  winnr < 0 ? 'vnew ' . fnameescape(command) : winnr . 'wincmd w'
  setlocal buftype=nowrite bufhidden=wipe nobuflisted noswapfile nowrap number
  silent! execute 'silent %!'. command
  silent! redraw
  silent! execute 'au BufUnload <buffer> execute bufwinnr(' . bufnr('#') . ') . ''wincmd w'''
  silent! execute 'nnoremap <silent> <buffer> <LocalLeader>r :call <SID>ExecuteInShell(''' . command . ''')<CR>'
  silent! execute 'wincmd w'
  " echo 'Shell command ' . command . ' executed.'
endfunction
command! -complete=shellcmd -nargs=+ Shell call s:ExecuteInShell(<q-args>)
cabbrev shell Shell

After that, in vim run command :shell python ~/p.py as example. And you will get the output in splitted window.

  • After changes in p.py as example you will run the same command again, this function will not create new window again, it will display the result in the previous(same) splitted window.

Solution 12 - Vim

Just use colon and exclamatory mark as shown below

>:!< script_name>

Solution 13 - Vim

I'd recommend the plugin quickrun. It's fast and simple to configure. Here's a little demonstration: enter image description here

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAlex BolotovView Question on Stackoverflow
Solution 1 - VimR. Martinho FernandesView Answer on Stackoverflow
Solution 2 - VimBrian CarperView Answer on Stackoverflow
Solution 3 - VimGediminas BukauskasView Answer on Stackoverflow
Solution 4 - VimSebastian BartosView Answer on Stackoverflow
Solution 5 - VimTimur FanshteynView Answer on Stackoverflow
Solution 6 - Vimapostl3polView Answer on Stackoverflow
Solution 7 - VimJack M.View Answer on Stackoverflow
Solution 8 - VimAngieView Answer on Stackoverflow
Solution 9 - VimxorpaulView Answer on Stackoverflow
Solution 10 - VimJetrockView Answer on Stackoverflow
Solution 11 - VimIgor KomarView Answer on Stackoverflow
Solution 12 - VimSarathView Answer on Stackoverflow
Solution 13 - VimTornaxO7View Answer on Stackoverflow