Cara mengeksekusi file yang saya edit di Vi (m)


101

Bagaimana cara mengeksekusi file yang saya edit di Vi (m) dan mendapatkan output di jendela terpisah (seperti di SciTE)?

Tentu saja saya bisa menjalankannya seperti itu:

:!scriptname

Tetapi apakah mungkin untuk menghindari penulisan nama skrip dan bagaimana cara mendapatkan output di jendela terpisah, bukan di bagian bawah layar?


21
:!% akan membiarkan Anda menghindari penulisan 'scriptname'. Solusi di bawah ini lebih baik, tetapi saya pikir saya akan menyebutkan ini jika Anda memutuskan:!% Cukup baik.
terlalu banyak berpikir pada

11
Catatan lain, Anda dapat menggunakan%: p (bukan hanya%) untuk merujuk ke jalur absolut file saat ini. Ini mungkin diperlukan jika direktori Anda saat ini ada di tempat lain.
andy

4
untuk menjalankan skrip ruby:! ruby% akan berhasil
Alexis Perrier

1
@andy:!%: p juga memutuskan tidak memiliki direktori di $ PATH
MayTheSForceBeWithYou

2
Dan :!"%:p"untuk mengatasi spasi.
OJFord

Jawaban:


109

Ada makeperintahnya. Ini menjalankan perintah yang ditetapkan dalam makeprgopsi. Gunakan %sebagai tempat penampung untuk nama file saat ini. Misalnya, jika Anda mengedit skrip python:

:set makeprg=python\ %

Ya, Anda harus keluar dari ruang angkasa. Setelah ini, Anda cukup menjalankan:

:make

Jika mau, Anda dapat mengatur autowriteopsi dan ini akan disimpan secara otomatis sebelum menjalankan makeprg:

:set autowrite

Ini menyelesaikan bagian eksekusi. Tidak tahu cara apa pun untuk mendapatkan keluaran itu ke jendela terpisah yang tidak melibatkan pengalihan ke file.


5
Sebenarnya, solusi Anda menghasilkan output ke jendela terpisah. Gunakan :copenuntuk membuka "daftar kesalahan" yang dihasilkan dengan menjalankan :make. Di jendelanya sendiri. Sayangnya, untuk mendapatkan hasil agar diformat dengan benar, beberapa errorformatopsi terakhir diperlukan. Jika tidak, keluaran akan dianggap dalam format yang dikeluarkan gcc.
Penyusun yang Mencolok

2
Anda sangat yakin tentang format kesalahan "finagling". Sepertinya beberapa kode perl yang pernah saya lihat ...
R. Martinho Fernandes

1
Fasilitas ini tersedia untuk 'membuat' proyek dari vim (memberikan vim kemampuan seperti IDE). Solusi Brian Carper ( :let f=expand("%")|vnew|execute '.!ruby "' . f . '"') meskipun terlihat samar, berfungsi persis seperti yang diminta oleh penulis pertanyaan.
AjayKumarBasuthkar

29

Untuk mengakses nama file buffer saat ini, gunakan %. Untuk membuatnya menjadi variabel Anda dapat menggunakan expand()fungsi tersebut. Untuk membuka jendela baru dengan buffer baru, gunakan :newatau :vnew. Untuk menyalurkan output dari perintah ke buffer saat ini, gunakan :.!. Menyatukan semuanya:

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

jelas mengganti rubydengan perintah apa pun yang Anda inginkan. Saya menggunakan executeagar saya bisa mengelilingi nama file dengan tanda kutip, jadi itu akan berfungsi jika nama file memiliki spasi di dalamnya.


3
@baboonWorksFine Gunakan :command! R let f=expand("%")|vnew|execute '.!ruby "' . f . '"'untuk dapat hanya menggunakan :Runtuk menjalankan perintahnya
xorpaul

Apakah mungkin membuat ini berjalan bahkan dengan skrip yang memerlukan masukan pengguna saat menjalankan?
ilstam

23

Vim memiliki !perintah ("bang") yang menjalankan perintah shell langsung dari jendela VIM. Selain itu memungkinkan peluncuran urutan perintah yang terhubung dengan pipa dan membaca stdout.

Sebagai contoh:

! node %

setara dengan membuka jendela prompt perintah dan meluncurkan perintah:

cd my_current_directory 
node my_current_file

Lihat "Tips Vim: Bekerja dengan perintah eksternal" untuk detailnya.


11

Saya memiliki jalan pintas untuk itu di vimrc saya:

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>

Ini menulis buffer saat ini, membuat file saat ini dapat dieksekusi (hanya unix), mengeksekusinya (hanya unix) dan mengalihkan output ke .tmp.xyz, kemudian membuat tab baru, membaca file dan kemudian menghapusnya.

Memecahnya:

: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
Saya sangat menyukai solusi Anda, dan setelah beberapa saat menggunakannya, saya merasa solusi tersebut dapat ditingkatkan. Jadi, inilah pendapat saya: :w<CR>:silent !chmod +x %:p<CR>:silent !%:p 2>&1 | tee ~/.vim/output<CR>:split ~/.vim/output<CR>:redraw!<CR>- ini mengalihkan baik stdout dan stderr ke file temp, dan sebelum melakukannya, ini mencetak semuanya ke stdout, jadi jika skrip membutuhkan waktu lama untuk dijalankan Anda benar-benar melihatnya berfungsi. Juga, ini tidak bergantung pada direktori (saya mendapatkan kesalahan saat membuka file dengan jalur absolutnya). Namun, itu tidak menjalankan skrip secara interaktif, dan saya belum menemukan cara untuk membuatnya demikian.
Kirill G

1
fyi - pada solusi @Cyril, saya harus keluar dari simbol pipa: | -> \ |
mpettis


3

Vim 8 memiliki terminal interaktif bawaan. Untuk menjalankan skrip bash saat ini dalam panel terpisah:

:terminal bash %

atau singkatnya

:ter bash %

% memperluas ke nama file saat ini.

Dari :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

Saya menggunakan mekanisme yang sedikit lebih mengganggu melalui peta:

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

Buat saja jadi saya tidak perlu menabung, lalu pergi. Pergi saja.


1
Jika Anda menyetel opsi tulis otomatis, Anda dapat menjalankan: make and it ... auto save before.
R. Martinho Fernandes

1

Anda dapat menggunakan plugin bexec dari vim . Sepengetahuan saya, versi terbaru adalah 0,5.

Kemudian:

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

Di dalam vim itu sendiri saat mengedit file .vba lakukan:

:so %

Beberapa keluaran akan muncul memberi tahu Anda bahwa bexec.vim telah ditulis serta dokumentasinya, dll ..

Sekarang, Anda dapat mengujinya dengan membuka (skrip bahasa apa pun yang memiliki #! Interpreter berfungsi dengan baik) di vim dan menjalankan

:Bexec 

Catatan: Saya ingin perpecahan menjadi vertikal daripada horizontal, jadi saya lakukan:

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

dan mengubah nilai dari "hor" menjadi "ver" ..

Saya tahu ini pertanyaan lama, tapi saya harap ini bisa membantu seseorang di luar sana. Saya telah mengalami masalah yang sama saat mengambil kursus Teknik Startup Coursera di mana profesor Palaji menggunakan Emacs dan saya tidak suka Emacs ..


Anda harus mengubah pengaturan terkait preferensi di .vimrc lokal Anda. bexec menawarkan pengaturan "let bexec_splitdir = 'hor'" yang dapat melakukannya tanpa mengubah kode plugin.
Saurabh Hirani

0

Berdasarkan jawaban @SethKriticos dan @Cyril, saya sekarang menggunakan yang berikut:

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>

Gunakan F9 untuk menyiapkan jendela baru dan F2 untuk menjalankan skrip dan tee ke file output Anda.

Saya juga menambahkan nama skrip ke nama file keluaran, sehingga Anda dapat menggunakan ini untuk beberapa skrip pada saat yang bersamaan.


0

Di Anda, .vimrcAnda dapat menempelkan fungsi ini

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

Setelah itu, di vimjalankan perintah :shell python ~/p.pysebagai contoh. Dan Anda akan mendapatkan output di jendela terbelah. + Setelah perubahan p.pysebagai contoh Anda akan menjalankan perintah yang sama lagi, fungsi ini tidak akan membuat jendela baru lagi, ini akan menampilkan hasilnya di jendela terpisah sebelumnya (sama).


Ini luar biasa, terima kasih! Bagaimana Anda mengubahnya untuk menjalankan kembali saat buffer ditulis lagi?
elzi

0

@tokopedia

Saya mencari skrip ini (python / Windows) cukup lama. Karena tidak ada "tee" di Windows, saya mengubahnya menjadi:

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

Cukup gunakan titik dua dan tanda seru seperti yang ditunjukkan di bawah ini

:! <script_name>


0

Saya akan merekomendasikan plugin quickrun . Cepat dan mudah untuk dikonfigurasi. Berikut sedikit demonstrasi: masukkan deskripsi gambar di sini

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.