Alex Bolotov
Alex Bolotov

Reputation: 8971

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

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?

Upvotes: 114

Views: 81975

Answers (13)

TornaxO7
TornaxO7

Reputation: 1299

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

Upvotes: 0

Sarath
Sarath

Reputation: 61

Just use colon and exclamatory mark as shown below

:!< script_name>

Upvotes: 1

apostl3pol
apostl3pol

Reputation: 984

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.

Upvotes: 7

Jetrock
Jetrock

Reputation: 113

@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>

Upvotes: 0

Iorrrrrrrrrr
Iorrrrrrrrrr

Reputation: 422

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.

Upvotes: 0

xorpaul
xorpaul

Reputation: 207

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.

Upvotes: 0

Angie
Angie

Reputation: 11

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..

Upvotes: 1

Sebastian Bartos
Sebastian Bartos

Reputation: 2497

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

Upvotes: 11

Gediminas Bukauskas
Gediminas Bukauskas

Reputation: 251

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.

Upvotes: 25

Timur Fanshteyn
Timur Fanshteyn

Reputation: 2296

For Shell script I've used

:set makeprg=%

:make

Upvotes: 4

R. Martinho Fernandes
R. Martinho Fernandes

Reputation: 234454

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.

Upvotes: 116

Jack M.
Jack M.

Reputation: 32070

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.

Upvotes: 1

Brian Carper
Brian Carper

Reputation: 72926

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.

Upvotes: 30

Related Questions