วิธีเรียกใช้ไฟล์ที่ฉันกำลังแก้ไขใน Vi (m)


103

วิธีเรียกใช้ไฟล์ที่ฉันแก้ไขใน Vi (m) และรับเอาต์พุตในหน้าต่างแยก (เช่นใน SciTE)

แน่นอนฉันสามารถดำเนินการได้เช่นนั้น:

:!scriptname

แต่เป็นไปได้หรือไม่ที่จะหลีกเลี่ยงการเขียนชื่อสคริปต์และวิธีรับเอาต์พุตในหน้าต่างแยกแทนที่จะอยู่ด้านล่างของหน้าจอ


21
:!% จะช่วยให้คุณหลีกเลี่ยงการเขียน "scriptname" วิธีแก้ปัญหาด้านล่างดีกว่า แต่ฉันคิดว่าฉันจะพูดถึงสิ่งนี้ในกรณีที่คุณตัดสินใจ:!% ดีพอ
overthink

11
หมายเหตุอีกประการหนึ่งคุณสามารถใช้%: p (แทนที่จะเป็น%) เพื่ออ้างถึงพา ธ สัมบูรณ์ของไฟล์ปัจจุบัน ซึ่งอาจจำเป็นหากไดเรกทอรีปัจจุบันของคุณอยู่ที่อื่น
andy

4
เพื่อเรียกใช้สคริปต์ทับทิม:! Ruby% จะทำเคล็ดลับ
Alexis Perrier

1
@andy:!%: p ยังแก้ปัญหาไม่ให้ไดเรกทอรีอยู่ใน $ PATH
MayTheSForceBeWithYou

2
และ:!"%:p"เพื่อรับมือกับช่องว่าง
OJFord

คำตอบ:


110

มีmakeคำสั่ง มันเรียกใช้ชุดคำสั่งในmakeprgตัวเลือก ใช้%เป็นตัวยึดสำหรับชื่อไฟล์ปัจจุบัน ตัวอย่างเช่นหากคุณกำลังแก้ไขสคริปต์ python:

:set makeprg=python\ %

ใช่คุณต้องหนีออกจากพื้นที่ หลังจากนี้คุณสามารถเรียกใช้:

:make

หากคุณต้องการคุณสามารถตั้งค่าautowriteตัวเลือกและจะบันทึกโดยอัตโนมัติก่อนที่จะเรียกใช้makeprg:

:set autowrite

สิ่งนี้จะแก้ส่วนที่ดำเนินการ ไม่ทราบวิธีใดในการรับผลลัพธ์นั้นไปยังหน้าต่างแยกที่ไม่เกี่ยวข้องกับการเปลี่ยนเส้นทางไปยังไฟล์


5
จริงๆแล้วโซลูชันของคุณจะได้รับผลลัพธ์ไปยังหน้าต่างแยก ใช้:copenเพื่อเปิด "รายการข้อผิดพลาด" ที่เกิดจากการเรียกใช้:make. ในหน้าต่างของตัวเอง น่าเสียดายที่เพื่อให้ได้ผลลัพธ์ที่ได้รับการจัดรูปแบบอย่างถูกต้องerrorformatจำเป็นต้องมีตัวเลือกขั้นสุดท้ายบางอย่าง มิฉะนั้นผลลัพธ์จะถูกสันนิษฐานว่าเป็นรูปแบบที่ gcc กำหนดไว้
Conspicuous Compiler

2
คุณแน่ใจเกี่ยวกับข้อผิดพลาด "finagling" ดูเหมือนรหัส perl ที่ฉันเคยเห็น ...
R. Martinho Fernandes

1
สิ่งอำนวยความสะดวกนี้มีให้สำหรับ 'make' ของโปรเจ็กต์จาก vim (ให้ความสามารถเหมือน IDE เป็นกลุ่ม) วิธีแก้ปัญหาของ Brian Carper ( :let f=expand("%")|vnew|execute '.!ruby "' . f . '"') แม้ว่าจะดูคลุมเครือ แต่ก็ใช้งานได้ตรงตามที่ผู้เขียนคำถามถาม
AjayKumarBasuthkar

29

ในการเข้าถึงชื่อไฟล์ของบัฟเฟอร์ปัจจุบันให้ใช้%. เพื่อให้เป็นตัวแปรคุณสามารถใช้expand()ฟังก์ชัน เพื่อเปิดหน้าต่างใหม่ด้วยกันชนใหม่ใช้หรือ:new ท่อผลลัพธ์จากคำสั่งลงในบัฟเฟอร์ปัจจุบันการใช้งาน:vnew :.!วางมันทั้งหมดเข้าด้วยกัน:

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

เห็นได้ชัดว่าแทนที่rubyด้วยคำสั่งที่คุณต้องการ ฉันใช้executeเพื่อให้ฉันสามารถล้อมรอบชื่อไฟล์ด้วยเครื่องหมายคำพูดดังนั้นมันจะใช้ได้ถ้าชื่อไฟล์มีช่องว่างอยู่


3
@baboonWorksFine ใช้ :command! R let f=expand("%")|vnew|execute '.!ruby "' . f . '"'เพื่อให้สามารถใช้:Rคำสั่งได้
xorpaul

เป็นไปได้ไหมที่จะทำให้สิ่งนี้ทำงานแม้กับสคริปต์ที่ต้องป้อนข้อมูลโดยผู้ใช้ขณะดำเนินการ
ilstam

23

Vim มี!คำสั่ง ("bang") ซึ่งรันคำสั่งเชลล์โดยตรงจากหน้าต่าง VIM นอกจากนี้ยังอนุญาตให้เรียกใช้ลำดับของคำสั่งที่เชื่อมต่อกับ pipe และอ่าน stdout

ตัวอย่างเช่น:

! node %

เทียบเท่ากับการเปิดหน้าต่างพรอมต์คำสั่งและเรียกใช้คำสั่ง:

cd my_current_directory 
node my_current_file

ดูเคล็ดลับ "ที่เป็นกลุ่ม: การทำงานกับคำสั่งภายนอก"สำหรับรายละเอียด


11

ฉันมีทางลัดสำหรับสิ่งนั้นใน 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>

สิ่งนี้เขียนบัฟเฟอร์ปัจจุบันทำให้ไฟล์ปัจจุบันสามารถเรียกใช้งานได้ (unix เท่านั้น) เรียกใช้งาน (unix เท่านั้น) และเปลี่ยนทิศทางเอาต์พุตไปที่. tmp.xyz จากนั้นสร้างแท็บใหม่อ่านไฟล์แล้วลบออก

ทำลายมันลง:

: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
ฉันชอบโซลูชันของคุณมากและหลังจากใช้งานไปสักพักฉันก็รู้สึกว่าสามารถปรับปรุงได้ ดังนั้นนี่คือสิ่งที่ฉันใช้: :w<CR>:silent !chmod +x %:p<CR>:silent !%:p 2>&1 | tee ~/.vim/output<CR>:split ~/.vim/output<CR>:redraw!<CR>- สิ่งนี้เปลี่ยนเส้นทางทั้ง stdout และ stderr ไปยังไฟล์ temp และก่อนที่จะทำเช่นนั้นมันจะพิมพ์ทุกอย่างเป็น stdout ดังนั้นหากสคริปต์ใช้เวลานานในการรันคุณจะเห็นว่ามันใช้งานได้จริง นอกจากนี้ยังไม่ขึ้นกับไดเรกทอรี (ฉันได้รับข้อผิดพลาดเมื่อเปิดไฟล์โดยใช้พา ธ สัมบูรณ์) อย่างไรก็ตามมันไม่ได้เรียกใช้สคริปต์แบบโต้ตอบและฉันไม่พบวิธีที่จะทำให้เป็นเช่นนั้น
Kirill G

1
fyi - ในการแก้ปัญหาของ @Cyril ฉันต้องหนีสัญลักษณ์ท่อ: | -> \ |
mpettis


3

Vim 8 มีเทอร์มินัลแบบโต้ตอบในตัวในการรันสคริปต์ทุบตีปัจจุบันในบานหน้าต่างแยก:

:terminal bash %

หรือสั้น ๆ

:ter bash %

% ขยายเป็นชื่อไฟล์ปัจจุบัน

จาก: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

ฉันใช้กลไกที่ล่วงล้ำมากขึ้นเล็กน้อยผ่านแผนที่:

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

แค่ทำให้ฉันไม่ต้องบันทึกแล้วไป เพียงแค่ไป.


1
หากคุณตั้งค่าตัวเลือกเขียนอัตโนมัติคุณสามารถเรียกใช้: make and it ... auto save before
R.Martinho Fernandes

1

คุณสามารถใช้เสียงเรียกเข้าเป็นปลั๊กอินbexec ตามความรู้ของฉันเวอร์ชันล่าสุดคือ 0.5

จากนั้น:

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

ภายในกลุ่มตัวเองในขณะที่แก้ไขไฟล์. vba ทำ:

:so %

ผลลัพธ์บางอย่างจะแสดงขึ้นเพื่อแจ้งให้คุณทราบว่าbexec.vimถูกเขียนรวมถึงเอกสารประกอบ ฯลฯ

ตอนนี้คุณสามารถทดสอบได้โดยเปิด (สคริปต์ภาษาใดก็ได้ที่มีล่าม #! ทำงานได้อย่างถูกต้อง) ในกลุ่มและเรียกใช้

:Bexec 

หมายเหตุ: ฉันต้องการให้การแบ่งเป็นแนวตั้งมากกว่าแนวนอนดังนั้นฉันจึงทำ:

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

และเปลี่ยนค่าของจาก "hor" เป็น "ver" ..

ฉันรู้ว่ามันเป็นคำถามเก่า แต่ฉันหวังว่านี่จะช่วยใครสักคนได้ ฉันประสบปัญหาเดียวกันในขณะที่เรียนหลักสูตรวิศวกรรมเริ่มต้นของ Coursera ซึ่งศาสตราจารย์ Palaji ใช้ Emacs และฉันไม่ชอบ Emacs ..


คุณควรเปลี่ยนค่ากำหนดที่เกี่ยวข้องกับการตั้งค่าใน. vimrc ในเครื่องของคุณ bexec เสนอการตั้งค่า "let bexec_splitdir = 'hor'" ซึ่งสามารถทำได้โดยไม่ต้องแก้ไขโค้ดปลั๊กอิน
Saurabh Hirani

0

จากคำตอบของ @SethKriticos และ @Cyril ตอนนี้ฉันใช้สิ่งต่อไปนี้:

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>

ใช้ F9 เพื่อตั้งค่าหน้าต่างใหม่และ F2 เพื่อรันสคริปต์ของคุณและทีไปยังไฟล์เอาต์พุตของคุณ

ฉันยังเพิ่มชื่อสคริปต์ให้กับชื่อไฟล์เอาต์พุตเพื่อให้คุณสามารถใช้สิ่งนี้สำหรับหลายสคริปต์ในเวลาเดียวกัน


0

ในของ.vimrcคุณคุณสามารถวางฟังก์ชันนี้

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

หลังจากนั้นในvimคำสั่ง run :shell python ~/p.pyตามตัวอย่าง และคุณจะได้รับผลลัพธ์ในหน้าต่างแยก + หลังจากการเปลี่ยนแปลงในp.pyตัวอย่างคุณจะเรียกใช้คำสั่งเดิมอีกครั้งฟังก์ชันนี้จะไม่สร้างหน้าต่างใหม่อีกครั้งจะแสดงผลลัพธ์ในหน้าต่างแยกก่อนหน้า (เดียวกัน)


ยอดเยี่ยมมากขอบคุณ! คุณจะเปลี่ยนเป็นการรันซ้ำได้อย่างไรเมื่อมีการเขียนบัฟเฟอร์อีกครั้ง
elzi

0

@xorpaul

ฉันกำลังมองหาสคริปต์นี้ (python / Windows) มาระยะหนึ่งแล้ว เนื่องจากไม่มี "tee" ใน Windows ฉันจึงเปลี่ยนเป็น:

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

เพียงใช้โคลอนและเครื่องหมายอัศเจรีย์ตามที่แสดงด้านล่าง

:! <script_name>


0

ผมอยากแนะนำให้ปลั๊กอินquickrun การกำหนดค่าทำได้ง่ายและรวดเร็ว นี่คือการสาธิตเล็กน้อย: ป้อนคำอธิบายภาพที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.