Cách thực thi tệp tôi đang chỉnh sửa trong Vi (m)


101

Làm thế nào để thực thi tệp mà tôi đang chỉnh sửa trong Vi (m) và nhận đầu ra trong cửa sổ chia nhỏ (như trong SciTE)?

Tất nhiên tôi có thể thực hiện nó như vậy:

:!scriptname

Nhưng liệu có khả thi để tránh viết tên tập lệnh và cách lấy đầu ra trong cửa sổ chia nhỏ thay vì chỉ ở cuối màn hình?


21
:!% sẽ cho phép bạn tránh viết 'scriptname'. Các giải pháp bên dưới tốt hơn, nhưng tôi nghĩ tôi sẽ đề cập đến vấn đề này trong trường hợp bạn quyết định:!% Là đủ tốt.
suy nghĩ kỹ

11
Một lưu ý khác, bạn có thể sử dụng%: p (thay vì chỉ%) để tham chiếu đến đường dẫn tuyệt đối của tệp hiện tại. Điều này có thể cần thiết nếu thư mục hiện tại của bạn ở một nơi khác.
andy

4
! để kịch bản ruby chạy: ruby% sẽ làm các trick
Alexis Perrier

1
! @andy:%: p cũng giải quyết không có thư mục là trong $ PATH
MayTheSForceBeWithYou

2
:!"%:p"để đối phó với khoảng trắng.
OJFord

Câu trả lời:


109

makelệnh. Nó chạy lệnh được đặt trong makeprgtùy chọn. Sử dụng %làm trình giữ chỗ cho tên tệp hiện tại. Ví dụ: nếu bạn đang chỉnh sửa tập lệnh python:

:set makeprg=python\ %

Có, bạn cần phải thoát khỏi không gian. Sau đó, bạn chỉ cần chạy:

:make

Nếu muốn, bạn có thể đặt autowritetùy chọn và nó sẽ tự động lưu trước khi chạy makeprg:

:set autowrite

Điều này giải quyết phần thực thi. Không biết bất kỳ cách nào để đưa đầu ra đó vào một cửa sổ phân tách không liên quan đến chuyển hướng đến tệp.


5
Trên thực tế, giải pháp của bạn có kết quả đầu ra là một cửa sổ chia nhỏ. Sử dụng :copenđể mở "danh sách lỗi" được tạo ra bằng cách chạy :make. Trong cửa sổ riêng của nó. Thật không may, để có được đầu ra được định dạng đúng, một số tài chính của errorformattùy chọn là cần thiết. Nếu không, đầu ra sẽ được coi là có định dạng mà gcc đưa ra.
Dễ thấy Compiler

2
Bạn chắc chắn về định dạng lỗi "tài chính". Nó trông giống như một số mã perl Tôi đã nhìn thấy ...
R. Martinho Fernandes

1
Cơ sở này có sẵn để 'thực hiện' dự án từ vim (cung cấp cho vim khả năng giống như IDE). Giải pháp của Brian Carper ( :let f=expand("%")|vnew|execute '.!ruby "' . f . '"') mặc dù có vẻ khó hiểu, nhưng hoạt động chính xác như tác giả của câu hỏi yêu cầu.
AjayKumarBasuthkar

29

Để truy cập tên tệp của bộ đệm hiện tại, hãy sử dụng %. Để đưa nó vào một biến, bạn có thể sử dụng expand()hàm. Để mở một cửa sổ mới với bộ đệm mới, hãy sử dụng :newhoặc :vnew. Để chuyển đầu ra từ một lệnh vào bộ đệm hiện tại, hãy sử dụng :.!. Để tất cả chúng cùng nhau:

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

rõ ràng thay thế rubybằng bất kỳ lệnh nào bạn muốn. Tôi đã sử dụng executeđể tôi có thể đặt tên tệp trong dấu ngoặc kép, vì vậy nó sẽ hoạt động nếu tên tệp có khoảng trắng trong đó.


3
@baboonWorksFine Sử dụng :command! R let f=expand("%")|vnew|execute '.!ruby "' . f . '"'để có thể chỉ sử dụng :Rđể thực hiện lệnh của anh ấy
xorpaul

Có thể làm cho điều này chạy ngay cả với các tập lệnh yêu cầu người dùng nhập trong khi thực thi không?
ilstam

23

Vim has !("bang") lệnh thực thi lệnh shell trực tiếp từ cửa sổ VIM. Hơn nữa, nó cho phép khởi chạy chuỗi lệnh được kết nối với đường ống và đọc stdout.

Ví dụ:

! node %

tương đương với việc mở cửa sổ nhắc lệnh và khởi chạy các lệnh:

cd my_current_directory 
node my_current_file

Xem "Mẹo Vim: Làm việc với các lệnh bên ngoài" để biết chi tiết.


11

Tôi có một phím tắt cho điều đó trong vimrc của mình:

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>

Thao tác này ghi bộ đệm hiện tại, làm cho tệp hiện tại có thể thực thi (chỉ unix), thực thi nó (chỉ unix) và chuyển hướng đầu ra thành .tmp.xyz, sau đó tạo một tab mới, đọc tệp và sau đó xóa nó.

Chia nhỏ nó:

: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
Tôi thích giải pháp của bạn rất nhiều, và sau một thời gian sử dụng nó, tôi cảm thấy rằng nó có thể được cải thiện. Vì vậy, đây là lý do của tôi: :w<CR>:silent !chmod +x %:p<CR>:silent !%:p 2>&1 | tee ~/.vim/output<CR>:split ~/.vim/output<CR>:redraw!<CR>- điều này chuyển hướng cả stdout và stderr đến tệp tạm thời và trước khi làm như vậy, nó in mọi thứ ra stdout, vì vậy nếu một tập lệnh mất nhiều thời gian để chạy, bạn thực sự thấy nó hoạt động. Ngoài ra, nó không phụ thuộc vào thư mục (tôi đã gặp lỗi khi mở tệp bằng đường dẫn tuyệt đối của chúng). Tuy nhiên, nó không chạy các tập lệnh một cách tương tác và tôi chưa tìm ra cách để làm cho nó như vậy.
Kirill G

1
fyi - trên giải pháp của @Cyril, tôi phải thoát khỏi ký hiệu ống: | -> \ |
mpettis


3

Vim 8 có một thiết bị đầu cuối tương tác được tích hợp sẵn. Để chạy tập lệnh bash hiện tại trong một ngăn tách:

:terminal bash %

hay gọi tắt

:ter bash %

% mở rộng đến tên tệp hiện tại.

Từ :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

Tôi sử dụng một cơ chế xâm nhập hơn một chút thông qua các bản đồ:

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

Chỉ cần làm cho nó để tôi không phải tiết kiệm, sau đó đi. Chỉ cần đi thôi.


1
Nếu bạn đặt tùy chọn tự động ghi, bạn có thể chạy: make and it ... auto save trước đó.
R. Martinho Fernandes

1

Bạn có thể sử dụng plugin bexec của vim . Theo hiểu biết của tôi, phiên bản mới nhất là 0,5.

Sau đó:

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

Bên trong bản thân vim khi chỉnh sửa tệp .vba thực hiện:

:so %

Một số đầu ra sẽ hiển thị cho bạn biết rằng bexec.vim đã được viết cũng như tài liệu, v.v.

Bây giờ, bạn có thể kiểm tra nó bằng cách mở (bất kỳ tập lệnh ngôn ngữ nào có trình thông dịch #! Hoạt động bình thường) trong vim và chạy

:Bexec 

Lưu ý: Tôi muốn phần tách theo chiều dọc thay vì chiều ngang, vì vậy tôi đã làm:

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

và thay đổi giá trị của từ "hor" thành "ver" ..

Tôi biết đó là một câu hỏi cũ, nhưng tôi hy vọng điều này có thể giúp ích cho ai đó. Tôi đã gặp phải vấn đề tương tự khi tham gia khóa học Kỹ thuật khởi động của Coursera, nơi giáo sư Palaji sử dụng Emacs và tôi không thích Emacs ..


Bạn nên thay đổi cài đặt liên quan đến tùy chọn trong .vimrc cục bộ của bạn. bexec cung cấp cài đặt "let bexec_splitdir = 'hor'" có thể làm như vậy mà không cần sửa đổi mã plugin.
Saurabh Hirani

0

Dựa trên câu trả lời @SethKriticos và @Cyril, tôi hiện sử dụng câu trả lời sau:

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>

Sử dụng F9 để thiết lập cửa sổ mới và F2 để thực thi tập lệnh và tee cho tệp đầu ra của bạn.

Tôi cũng đã thêm tên tập lệnh vào tên tệp đầu ra để bạn có thể sử dụng tên này cho nhiều tập lệnh cùng một lúc.


0

Trong của .vimrcbạn, bạn có thể dán chức năng này

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

Sau đó, trong vimlệnh chạy :shell python ~/p.pylàm ví dụ. Và bạn sẽ nhận được đầu ra trong cửa sổ được chia nhỏ. + Sau khi thay đổi p.pyví dụ bạn sẽ chạy lại lệnh tương tự, chức năng này sẽ không tạo lại cửa sổ mới mà sẽ hiển thị kết quả ở cửa sổ đã tách (giống nhau) trước đó.


Điều này thật tuyệt vời, cảm ơn bạn! Làm thế nào bạn có thể thay đổi nó để chạy lại khi bộ đệm được ghi lại?
elzi

0

@xorpaul

Tôi đã tìm kiếm tập lệnh này (python / Windows) trong một thời gian khá dài. Vì không có "tee" trong Windows nên tôi đã thay đổi nó thành:

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

Chỉ cần sử dụng dấu hai chấm và dấu chấm than như hình dưới đây

:! <script_name>


0

Tôi muốn khuyên các plugin quickrun . Nó nhanh chóng và đơn giản để cấu hình. Đây là một minh chứng nhỏ: nhập mô tả hình ảnh ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.