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?

Alex Bolotov
la source
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.

R. Martinho Fernandes
la source
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.

Brian Carper
la source
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.

Gediminas Bukauskas
la source
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
Sébastien Bartos
la source
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
4

Pour le script Shell, j'ai utilisé

:set makeprg=%

:make
Timur Fanshteyn
la source
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.
apostl3pol
la source
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.

Jack M.
la source
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.

Angie
la source
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.

xorpaul
la source
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.

Igor Komar
la source
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>
Jetrock
la source
0

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

:! <nom_script>

Sarath
la source
0

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

TornaxO7
la source