2010-04-04 38 views
7

Khi tôi sử dụng:%! để chạy các nội dung của một tập tin thông qua một bộ lọc và bộ lọc không thành công (nó trả về một mã khác 0) và in một thông báo lỗi để stderr tôi nhận được tập tin của tôi thay thế bằng thông báo lỗi này. Có cách nào để nói vim bỏ qua lọc nếu bộ lọc trả về một mã trạng thái chỉ ra một lỗi và/hoặc bỏ qua đầu ra chương trình lọc ghi vào stderr?bộ lọc vim và stdout/stderr

Có những trường hợp bạn muốn tệp của mình được thay thế bằng đầu ra của bộ lọc nhưng thường thì hành vi này là sai. Tất nhiên tôi chỉ có thể hoàn tác việc lọc bằng một phím bấm nhưng nó không phải là tối ưu.

Ngoài ra tôi có một vấn đề tương tự khi viết tập lệnh vim tùy chỉnh để thực hiện việc lọc. Tôi có một kịch bản lệnh gọi một chương trình lọc với hệ thống() và thay thế tệp trong bộ đệm với đầu ra của nó nhưng dường như không có cách nào để phát hiện xem các dòng được trả về bởi hệ thống() có được viết thành stdout hay stderr hay không . Có cách nào để nói với họ ngoài trong kịch bản vim?

Trả lời

3

Bạn có thể sử dụng Python để phân biệt giữa stdout và stderr:

python import vim, subprocess 
python b=vim.current.buffer 
python line=vim.current.range.start 
python p=subprocess.Popen(["command", "argument", ...], stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True) 
python returncode=p.poll() 
python if not returncode: b.append(("STDOUT:\n"+p.stdout.read()+"\nSTDERR:\n"+p.stderr.read()).split("\n"), line) 
+0

Tất nhiên! Với mọi ngôn ngữ kịch bản "thực", nó không phải là vấn đề gì cả. Không nghĩ về điều đó. Mặc dù tôi muốn kịch bản vim nếu có thể bởi vì tôi không muốn có nhiều phụ thuộc vào kịch bản của tôi hơn là cần thiết. – ahe

+1

Tôi biết chỉ có một cách khác: sử dụng 'system()', chuyển hướng stderr đến một tệp tạm thời (hoặc '/ dev/null'), lưu stdout vào một số biến và sử dụng' v: shell_error' để xác định liệu một lệnh có bị lỗi trước hay không đệm ghi đè. Lưu ý rằng các bộ lọc ':!' Thay thế «!» Bằng lệnh trước đó và «%» với tên tệp hiện tại trong khi 'system()' thì không. – ZyX

3

:!{cmd} Thực thi {cmd} với vỏ và đặt v:shell_error.

Nếu bạn tình cờ thiết lập ánh xạ để gọi bộ lọc của bạn, bạn có thể làm một cái gì đó như sau:

function! UndoIfShellError() 
    if v:shell_error 
     undo 
    endif 
endfuntion 

nmap <leader>filter :%!/path/to/filter<CR>:call UndoIfShellError()<CR> 
+0

Bí quyết tuyệt vời :). Thực ra tôi hy vọng có một mặt dây chuyền nhạy cảm với lỗi cho cú pháp:! {Cmd} mà tôi vừa bỏ qua. Nhưng ngày càng nhiều tôi sợ rằng không có cú pháp thay thế như vậy tồn tại. – ahe

1

Một thay thế sẽ là để chạy các lệnh lọc như nó đổi các tập tin trên đĩa.

Ví dụ, đối gofmt (www.golang.org) Tôi có những ánh xạ tại chỗ:

map <f9> :w<CR>:silent !gofmt -w=true %<CR>:e<CR> 
imap <f9> <ESC>:w<CR>:silent !gofmt -w=true %<CR>:e<CR> 

Giải thích: : w - lưu tập tin : im lặng - tránh nhấn enter vào cuối % - vượt qua tập tin để gofmt -w = true - kể gofmt để viết lại các tập tin : e - nói vim để tải lại sửa đổi tập tin

0

Đây là những gì tôi đã kết thúc thực hiện:

function MakeItAFunction(line1, line2, args) 
    let l:results=system() " call filter via system or systemlist 
    if v:shell_error 
    "no changes were ever actually made! 
    echom "Error with etc etc" 
    echom results 
    endif 
    "process results if anything needed? 

    " delete lines but don't put in register: 
    execute a:line1.",".a:line2." normal \"_dd" 
    call append(a:line1-1, l:result) " add lines 
    call cursor(a:line1, 1) " back to starting place 
    " echom any messages 
endfunction 
command -range <command keys> MakeItAFunction(<line1>,<line2>,<q-args>) 
"           or <f-args>, etc. 

Bạn có thể xem mã đầy đủ của tôi tại http://vim.wikia.com/wiki/Perl_compatible_regular_expressions

Đó là phức tạp, nhưng nó hoạt động và khi nó được sử dụng, nó khá minh bạch và duyên dáng. Hy vọng rằng sẽ giúp trong bất kỳ cách nào!

Các vấn đề liên quan