Cómo ejecutar el archivo que estoy editando en Vi (m)

101

¿Cómo ejecutar el archivo que estoy editando en Vi (m) y obtener la salida en una ventana dividida (como en SciTE)?

Por supuesto que podría ejecutarlo así:

:!scriptname

Pero, ¿es posible evitar escribir el nombre del script y cómo obtener la salida en la ventana dividida en lugar de la parte inferior de la pantalla?

Alex Bolotov
fuente
21
:!% le permitirá evitar escribir 'scriptname'. Las siguientes soluciones son mejores, pero pensé que mencionaría esto en caso de que decidas:!% Es lo suficientemente bueno.
pensar demasiado
11
Otra nota, puede usar%: p (en lugar de solo%) para referirse a la ruta absoluta del archivo actual. Esto puede ser necesario si su directorio actual está en otro lugar.
Andy
4
para ejecutar scripts de ruby:! ruby% hará el truco
Alexis Perrier
1
@andy:!%: p también resuelve no tener el directorio en $ PATH
MayTheSForceBeWithYou
2
Y :!"%:p"para hacer frente a los espacios en blanco.
OJFord

Respuestas:

109

Ahí está el makecomando. Ejecuta el comando establecido en la makeprgopción. Úselo %como marcador de posición para el nombre del archivo actual. Por ejemplo, si estuviera editando una secuencia de comandos de Python:

:set makeprg=python\ %

Sí, necesitas escapar del espacio. Después de esto, simplemente puede ejecutar:

:make

Si lo desea, puede configurar la autowriteopción y se guardará automáticamente antes de ejecutar makeprg:

:set autowrite

Esto resuelve la parte de ejecución. No conozco ninguna forma de obtener esa salida en una ventana dividida que no implique la redirección al archivo.

R. Martinho Fernandes
fuente
5
En realidad, su solución obtiene el resultado en una ventana dividida. Utilice :copenpara abrir la "lista de errores" producida al ejecutar :make.en su propia ventana. Desafortunadamente, para que la salida se formatee correctamente, errorformates necesario manipular la opción. De lo contrario, se presumirá que la salida tiene el formato que envía gcc.
Compilador conspicuo
2
Estás muy seguro de "manipular" el formato de error. Parece un código Perl que he visto ...
R. Martinho Fernandes
1
Esta función está disponible para 'hacer' un proyecto desde vim (le da a vim la capacidad similar a IDE). La solución de Brian Carper ( :let f=expand("%")|vnew|execute '.!ruby "' . f . '"'), aunque parece críptica, funciona exactamente como lo pidió el autor de la pregunta.
AjayKumarBasuthkar
29

Para acceder al nombre de archivo del búfer actual, use %. Para convertirlo en una variable, puede usar la expand()función. Para abrir una nueva ventana con un búfer nuevo, use :newo :vnew. Para canalizar la salida de un comando al búfer actual, use :.!. Poniendolo todo junto:

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

obviamente reemplazando rubycon cualquier comando que desee. Lo utilicé executepara poder rodear el nombre del archivo entre comillas, por lo que funcionará si el nombre del archivo tiene espacios.

Brian Carper
fuente
3
@baboonWorksFine Use :command! R let f=expand("%")|vnew|execute '.!ruby "' . f . '"'para poder usar solo :Rpara ejecutar su comando
xorpaul
¿Sería posible ejecutar esto incluso con scripts que requieran la entrada del usuario durante la ejecución?
ilstam
23

Vim tiene un !comando ("bang") que ejecuta el comando de shell directamente desde la ventana de VIM. Además, permite lanzar una secuencia de comandos que están conectados con pipe y leer stdout.

Por ejemplo:

! node %

es equivalente a abrir la ventana del símbolo del sistema y ejecutar comandos:

cd my_current_directory 
node my_current_file

Consulte "Consejos de Vim: trabajar con comandos externos" para obtener más detalles.

Gediminas Bukauskas
fuente
11

Tengo un atajo para eso en mi 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>

Esto escribe el búfer actual, hace que el archivo actual sea ejecutable (solo unix), lo ejecuta (solo unix) y redirige la salida a .tmp.xyz, luego crea una nueva pestaña, lee el archivo y luego lo elimina.

Desglosando:

: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
Sebastián Bartos
fuente
2
Me gustó mucho tu solución y, después de un tiempo de usarla, sentí que se podía mejorar. Así que aquí está mi opinión: :w<CR>:silent !chmod +x %:p<CR>:silent !%:p 2>&1 | tee ~/.vim/output<CR>:split ~/.vim/output<CR>:redraw!<CR>esto redirige tanto el stdout como el stderr al archivo temporal, y antes de hacerlo, imprime todo en stdout, por lo que si un script tarda mucho en ejecutarse, realmente lo verá funcionando. Además, es independiente del directorio (recibía errores al abrir archivos por su ruta absoluta). Sin embargo, no ejecuta scripts de forma interactiva y no he encontrado la manera de hacerlo.
Kirill G
1
fyi - en la solución de @Cyril, tuve que escapar del símbolo de la tubería: | -> \ |
mpettis
4

Para el script de Shell que he usado

:set makeprg=%

:make
Timur Fanshteyn
fuente
3

Vim 8 tiene una terminal interactiva integrada. Para ejecutar el script bash actual en un panel dividido:

:terminal bash %

o para abreviar

:ter bash %

% se expande al nombre del archivo actual.

De :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.
apostl3pol
fuente
1

Utilizo un mecanismo un poco más intrusivo a través de mapas:

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

Simplemente lo hace para que no tenga que guardar, luego me voy. Solo vamos.

Jack M.
fuente
1
Si configura la opción de escritura automática, puede ejecutar: make y eso ... guarda automáticamente antes.
R. Martinho Fernandes
1

Puede usar el complemento bexec de vim . Que yo sepa, la última versión es 0.5.

Luego:

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

Dentro de vim mientras edita el archivo .vba, haga lo siguiente:

:so %

Aparecerá un resultado que le permitirá saber que se ha escrito bexec.vim , así como la documentación, etc.

Ahora, puede probarlo abriendo su (cualquier script de idioma que tenga un intérprete #! Funcionando correctamente) en vim y ejecute

:Bexec 

Nota: quería que la división fuera vertical en lugar de horizontal, así que lo hice:

$ 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]

y cambió el valor de "hor" a "ver".

Sé que es una vieja pregunta, pero espero que esto pueda ayudar a alguien. He estado corriendo en el mismo problema mientras tomaba el curso de Ingeniería de inicio de Coursera donde el profesor Palaji usa Emacs y no me gusta Emacs.

Angie
fuente
Debe cambiar la configuración relacionada con las preferencias en su .vimrc local. bexec ofrece la configuración "let bexec_splitdir = 'hor'" que puede hacerlo sin modificar el código del complemento.
Saurabh Hirani
0

Basado en las respuestas de @SethKriticos y @Cyril, ahora uso lo siguiente:

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 para configurar la nueva ventana y F2 para ejecutar su script y abrir su archivo de salida.

También agregué el nombre del script al nombre del archivo de salida, para que pueda usarlo para varios scripts al mismo tiempo.

xorpaul
fuente
0

En tu .vimrcpuedes pegar esta función

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

Después de eso, en el vimcomando de ejecución :shell python ~/p.pycomo ejemplo. Y obtendrá la salida en una ventana dividida. + Después de los cambios en p.pycomo ejemplo, ejecutará el mismo comando nuevamente, esta función no creará una nueva ventana nuevamente, mostrará el resultado en la ventana dividida anterior (la misma).

Igor Komar
fuente
¡Esto es genial, gracias! ¿Cómo podría cambiarlo para que se vuelva a ejecutar cuando se vuelva a escribir el búfer?
elzi
0

@xorpaul

Estuve buscando este script (python / Windows) durante bastante tiempo. Como no hay "tee" en Windows, lo cambié a:

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>
Jetrock
fuente
0

Simplemente use dos puntos y un signo de exclamación como se muestra a continuación

:! <script_name>

Sarath
fuente
0

Recomendaría el complemento quickrun . Es rápido y sencillo de configurar. Aquí hay una pequeña demostración: ingrese la descripción de la imagen aquí

TornaxO7
fuente