Como executar o arquivo que estou editando em Vi (m)

101

Como executar o arquivo que estou editando no Vi (m) e obter a saída na janela dividida (como no SciTE)?

Claro que eu poderia executá-lo assim:

:!scriptname

Mas é possível evitar escrever o nome do script e como obter a saída na janela dividida em vez de apenas na parte inferior da tela?

Alex Bolotov
fonte
21
:!% permitirá que você evite escrever 'scriptname'. As soluções abaixo são melhores, mas pensei em mencioná-las caso você decida:!% É bom o suficiente.
pense em
11
Outra observação, você pode usar%: p (em vez de apenas%) para se referir ao caminho absoluto do arquivo atual. Isso pode ser necessário se o seu diretório atual estiver em outro lugar.
Andy
4
para executar scripts Ruby:! ruby% fará o truque
Alexis Perrier
1
@andy:!%: p também resolve não ter o diretório no $ PATH
MayTheSForceBeWithYou
2
E :!"%:p"para lidar com espaços em branco.
OJFord,

Respostas:

109

Aí está o makecomando. Ele executa o comando definido na makeprgopção. Use %como um espaço reservado para o nome do arquivo atual. Por exemplo, se você estava editando um script Python:

:set makeprg=python\ %

Sim, você precisa escapar do espaço. Depois disso, você pode simplesmente executar:

:make

Se desejar, você pode definir a autowriteopção e ela será salva automaticamente antes de executar makeprg:

:set autowrite

Isso resolve a parte de execução. Não conheço nenhuma maneira de obter essa saída em uma janela dividida que não envolva o redirecionamento para o arquivo.

R. Martinho Fernandes
fonte
5
Na verdade, sua solução obtém a saída para uma janela dividida. Use :copenpara abrir a "lista de erros" produzida ao executar :make.em sua própria janela. Infelizmente, para que a saída seja formatada de maneira adequada, alguns detalhes sobre a errorformatopção são necessários. Caso contrário, a saída será presumida no formato gcc puts out.
Conspicuous Compiler
2
Você tem certeza sobre o formato de erro "finagling". Parece um código perl que eu vi ...
R. Martinho Fernandes
1
Este recurso está disponível para 'fazer' o projeto do vim (dá ao vim a capacidade de IDE). A solução de Brian Carper ( :let f=expand("%")|vnew|execute '.!ruby "' . f . '"') embora pareça enigmática, funciona exatamente como perguntado pelo autor da pergunta.
AjayKumarBasuthkar de
29

Para acessar o nome do arquivo do buffer atual, use %. Para colocá-lo em uma variável, você pode usar a expand()função. Para abrir uma nova janela com um novo buffer, use :newou :vnew. Para canalizar a saída de um comando para o buffer atual, use :.!. Juntando tudo:

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

obviamente substituindo rubycom qualquer comando que você deseja. Usei executepara colocar o nome do arquivo entre aspas, então funcionará se o nome do arquivo contiver espaços.

Brian Carper
fonte
3
@baboonWorksFine Use :command! R let f=expand("%")|vnew|execute '.!ruby "' . f . '"'para ser capaz de usar apenas :Rpara executar seu comando
xorpaul
Seria possível fazer isso funcionar mesmo com scripts que exigem entrada do usuário durante a execução?
ilstam
23

O Vim tem um !comando ("bang") que executa o comando shell diretamente da janela do VIM. Além disso, permite lançar uma sequência de comandos que estão conectados com o pipe e lêem stdout.

Por exemplo:

! node %

equivale a abrir a janela do prompt de comando e iniciar comandos:

cd my_current_directory 
node my_current_file

Consulte "Dicas do Vim: Trabalhando com comandos externos" para obter detalhes.

Gediminas Bukauskas
fonte
11

Tenho um atalho para isso no meu 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>

Isso grava o buffer atual, torna o arquivo atual executável (somente unix), executa-o (somente unix) e redireciona a saída para .tmp.xyz, em seguida, cria uma nova guia, lê o arquivo e o exclui.

Dividindo:

: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
Sebastian Bartos
fonte
2
Gostei muito da sua solução e, após um tempo de uso, senti que poderia ser melhorada. Então, aqui está minha opinião sobre isso: :w<CR>:silent !chmod +x %:p<CR>:silent !%:p 2>&1 | tee ~/.vim/output<CR>:split ~/.vim/output<CR>:redraw!<CR>- isso redireciona o stdout e o stderr para o arquivo temporário e, antes de fazer isso, imprime tudo no stdout, portanto, se um script demorar para ser executado, você o verá funcionando. Além disso, é independente do diretório (recebia erros ao abrir arquivos pelo caminho absoluto). No entanto, ele não executa scripts de forma interativa e não encontrei uma maneira de fazê-lo.
Kirill G
1
fyi - na solução de @Cyril, tive que escapar do símbolo do tubo: | -> \ |
mpettis
4

Para o script Shell que usei

:set makeprg=%

:make
Timur Fanshteyn
fonte
3

O Vim 8 tem um terminal interativo integrado. Para executar o script bash atual em um painel dividido:

:terminal bash %

ou para breve

:ter bash %

% expande para o nome do arquivo atual.

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
fonte
1

Eu uso um mecanismo um pouco mais intrusivo por meio de mapas:

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

Apenas faz com que eu não precise salvar e depois vá. Apenas vá.

Jack M.
fonte
1
Se você definir a opção autowrite, você pode executar: make and it ... auto saves before.
R. Martinho Fernandes
1

Você pode usar o plugin bexec do vim . Pelo que sei, a última versão é 0,5.

Então:

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

Dentro do próprio vim, ao editar o arquivo .vba, faça:

:so %

Alguma saída aparecerá informando que bexec.vim foi escrito, bem como a documentação, etc.

Agora, você pode testá-lo abrindo seu (qualquer script de idioma que tenha um #! Intérprete funcionando corretamente) no vim e execute

:Bexec 

Observação: eu queria que a divisão fosse vertical em vez de horizontal, então fiz:

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

e alterei o valor de "hor" para "ver" ..

Eu sei que é uma pergunta antiga, mas espero que isso possa ajudar alguém aí. Tenho enfrentado o mesmo problema durante o curso de Engenharia de Inicialização do Coursera, onde o professor Palaji usa o Emacs e eu não gosto do Emacs.

Angie
fonte
Você deve alterar as configurações relacionadas às preferências em seu .vimrc local. O bexec oferece a configuração "let bexec_splitdir = 'hor'" que pode fazer isso sem modificar o código do plugin.
Saurabh Hirani
0

Com base nas respostas de @SethKriticos e @Cyril, agora uso o seguinte:

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 a nova janela e F2 para executar seu script e iniciar seu arquivo de saída.

Também adicionei o nome do script ao nome do arquivo de saída, para que você possa usá-lo para vários scripts ao mesmo tempo.

xorpaul
fonte
0

No seu .vimrcvocê pode colar esta função

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

Depois disso, em vimrun command :shell python ~/p.pycomo exemplo. E você obterá a saída em janela dividida. + Após as alterações no p.pyexemplo você executará o mesmo comando novamente, esta função não criará uma nova janela novamente, ela exibirá o resultado na janela dividida anterior (mesma).

Igor Komar
fonte
Isso é incrível, obrigado! Como você pode alterá-lo para reexecutar quando o buffer for escrito novamente?
elzi 01 de
0

@xorpaul

Eu estava procurando por este script (python / Windows) há algum tempo. Como não há "tee" no Windows, mudei para:

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
fonte
0

Basta usar dois pontos e ponto de exclamação como mostrado abaixo

:! <script_name>

Sarath
fonte
0

Eu recomendo o Quickrun do plugin . É rápido e simples de configurar. Aqui está uma pequena demonstração: insira a descrição da imagem aqui

TornaxO7
fonte