Comment exécuter le fichier que j'édite dans Vi (m)


101

Comment exécuter le fichier que j'édite dans Vi (m) et obtenir la sortie dans une fenêtre fractionnée (comme dans SciTE)?

Bien sûr, je pourrais l'exécuter comme ça:

:!scriptname

Mais est-il possible d'éviter d'écrire le nom du script et comment obtenir la sortie dans une fenêtre fractionnée au lieu juste en bas de l'écran?


21
:!% vous permettra d'éviter d'écrire 'scriptname'. Les solutions ci-dessous sont meilleures, mais j'ai pensé mentionner ceci au cas où vous décideriez:!% Est assez bien.
Overhink le

11
Autre remarque, vous pouvez utiliser%: p (au lieu de seulement%) pour faire référence au chemin absolu du fichier actuel. Cela peut être nécessaire si votre répertoire actuel est ailleurs.
andy

4
pour exécuter des scripts ruby:! ruby% fera l'affaire
Alexis Perrier

1
@andy:!%: p résout également le fait que le répertoire ne se trouve pas dans le $ PATH
MayTheSForceBeWithYou

2
Et :!"%:p"pour faire face aux espaces.
OJFord

Réponses:


109

Il y a la makecommande. Il exécute la commande définie dans l' makeprgoption. À utiliser %comme espace réservé pour le nom de fichier actuel. Par exemple, si vous éditiez un script python:

:set makeprg=python\ %

Oui, vous devez vous échapper de l'espace. Après cela, vous pouvez simplement exécuter:

:make

Si vous le souhaitez, vous pouvez définir l' autowriteoption et elle sera automatiquement enregistrée avant d'exécuter le makeprg:

:set autowrite

Cela résout la partie d'exécution. Je ne connais aucun moyen d'obtenir cette sortie dans une fenêtre fractionnée qui n'implique pas de redirection vers un fichier.


5
En fait, votre solution obtient la sortie dans une fenêtre fractionnée. Utilisez :copenpour ouvrir la "liste des erreurs" produite en exécutant :make.dans sa propre fenêtre. Malheureusement, pour que la sortie soit formatée correctement, certaines modifications de l' errorformatoption sont nécessaires. Sinon, la sortie sera présumée être au format émis par gcc.
Compilateur remarquable

2
Vous êtes vraiment sûr du format d'erreur "finagling". Cela ressemble à du code Perl que j'ai vu ...
R. Martinho Fernandes

1
Cette fonction est disponible pour «créer» un projet à partir de vim (donne à vim la capacité de type IDE). La solution de Brian Carper ( :let f=expand("%")|vnew|execute '.!ruby "' . f . '"') bien que semble cryptique, fonctionne exactement comme demandé par l'auteur de la question.
AjayKumarBasuthkar

29

Pour accéder au nom de fichier du tampon actuel, utilisez %. Pour l'intégrer dans une variable, vous pouvez utiliser la expand()fonction. Pour ouvrir une nouvelle fenêtre avec un nouveau tampon, utilisez :newou :vnew. Pour diriger la sortie d'une commande vers le tampon actuel, utilisez :.!. Mettre tous ensemble:

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

remplaçant évidemment rubypar la commande que vous voulez. J'ai utilisé executepour que je puisse entourer le nom de fichier avec des guillemets, donc cela fonctionnera si le nom de fichier contient des espaces.


3
@baboonWorksFine Utilisez :command! R let f=expand("%")|vnew|execute '.!ruby "' . f . '"'pour pouvoir simplement utiliser :Rpour exécuter sa commande
xorpaul

Serait-il possible de faire cela même avec des scripts qui nécessitent une entrée de l'utilisateur lors de l'exécution?
ilstam

23

Vim a une commande !("bang") qui exécute la commande shell directement depuis la fenêtre VIM. De plus, il permet de lancer une séquence de commandes qui sont connectées avec pipe et lisent stdout.

Par exemple:

! node %

équivaut à ouvrir la fenêtre d'invite de commande et à lancer des commandes:

cd my_current_directory 
node my_current_file

Voir "Astuces Vim: Travailler avec des commandes externes" pour plus de détails.


11

J'ai un raccourci pour cela dans mon 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>

Cela écrit le tampon actuel, rend le fichier actuel exécutable (unix uniquement), l'exécute (unix uniquement) et redirige la sortie vers .tmp.xyz, puis crée un nouvel onglet, lit le fichier puis le supprime.

Décomposer:

: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

2
J'ai beaucoup aimé votre solution, et après un certain temps d'utilisation, j'ai senti qu'elle pouvait être améliorée. Alors, voici mon point de vue: :w<CR>:silent !chmod +x %:p<CR>:silent !%:p 2>&1 | tee ~/.vim/output<CR>:split ~/.vim/output<CR>:redraw!<CR>- cela redirige à la fois stdout et stderr vers le fichier temporaire, et avant de le faire, il imprime tout sur stdout, donc si un script prend du temps à s'exécuter, vous le voyez réellement fonctionner. En outre, il est indépendant du répertoire (j'obtenais des erreurs lors de l'ouverture des fichiers par leur chemin absolu). Cependant, il n'exécute pas de scripts de manière interactive et je n'ai pas trouvé de moyen de le faire.
Kirill G

1
Pour info - sur la solution de @Cyril, j'ai dû échapper au symbole du tuyau: | -> \ |
mpettis


3

Vim 8 a un terminal interactif intégré. Pour exécuter le script bash actuel dans un volet divisé:

:terminal bash %

ou pour faire court

:ter bash %

% se développe au nom de fichier actuel.

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.

1

J'utilise un mécanisme un peu plus intrusif à travers les cartes:

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

Cela fait simplement que je n'ai pas à économiser, alors partez. Juste aller.


1
Si vous définissez l'option d'écriture automatique, vous pouvez exécuter: make et il ... enregistre automatiquement avant.
R. Martinho Fernandes le

1

Vous pouvez utiliser le plugin bexec de vim . À ma connaissance, la dernière version est la 0.5.

Ensuite:

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

À l'intérieur de vim lui-même lors de l'édition du fichier .vba, procédez comme suit:

:so %

Une sortie s'affichera pour vous informer que bexec.vim a été écrit ainsi que la documentation, etc.

Maintenant, vous pouvez le tester en ouvrant votre (quel que soit le script de langue qui a un interpréteur #! Fonctionnant correctement) dans vim et exécutez

:Bexec 

Remarque: je voulais que la division soit verticale plutôt qu'horizontale, alors j'ai fait:

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

et a changé la valeur de "hor" à "ver".

Je sais que c'est une vieille question, mais j'espère que cela peut aider quelqu'un là-bas. J'ai couru dans le même problème en suivant le cours d'ingénierie de démarrage de Coursera où le professeur Palaji utilise Emacs et je n'aime pas Emacs.


Vous devez modifier les paramètres liés aux préférences dans votre fichier .vimrc local. bexec propose le paramètre "let bexec_splitdir = 'hor'" qui peut le faire sans modifier le code du plugin.
Saurabh Hirani

0

Sur la base des réponses @SethKriticos et @Cyril, j'utilise maintenant les éléments suivants:

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>

Utilisez F9 pour configurer la nouvelle fenêtre et F2 pour exécuter votre script et té vers votre fichier de sortie.

J'ai également ajouté le nom du script au nom du fichier de sortie, afin que vous puissiez l'utiliser pour plusieurs scripts en même temps.


0

Dans votre .vimrcvous pouvez coller cette fonction

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

Après cela, dans vim commande d'exécution :shell python ~/p.pycomme exemple. Et vous obtiendrez la sortie dans une fenêtre fractionnée. + Après des modifications dans l' p.pyexemple, vous exécuterez à nouveau la même commande, cette fonction ne créera plus de nouvelle fenêtre, elle affichera le résultat dans la (même) fenêtre fractionnée précédente.


C'est génial, merci! Comment pouvez-vous le modifier pour qu'il soit réexécuté lorsque le tampon est à nouveau écrit?
elzi

0

@xorpaul

Je cherchais ce script (python / Windows) depuis un certain temps. Comme il n'y a pas de "tee" dans Windows, je l'ai changé en:

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>

0

Utilisez simplement deux points et un point d'exclamation comme indiqué ci-dessous

:! <nom_script>


0

Je recommanderais le plugin quickrun . C'est simple et rapide à configurer. Voici une petite démonstration: entrez la description de l'image ici

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.