Jak wykonać plik, który edytuję w Vi (m)

101

Jak uruchomić plik, który edytuję w Vi (m) i uzyskać wynik w podzielonym oknie (jak w SciTE)?

Oczywiście mogłem to wykonać w ten sposób:

:!scriptname

Ale czy można uniknąć pisania nazwy skryptu i jak uzyskać dane wyjściowe w podzielonym oknie zamiast u dołu ekranu?

Alex Bolotov
źródło
21
:!% pozwoli ci uniknąć wpisywania „scriptname”. Poniższe rozwiązania są lepsze, ale pomyślałem, że wspomnę o tym, jeśli zdecydujesz:!% Jest wystarczająco dobre.
przemyślenie
11
Kolejna uwaga, możesz użyć%: p (zamiast tylko%), aby odnieść się do bezwzględnej ścieżki bieżącego pliku. Może to być konieczne, jeśli twój bieżący katalog znajduje się w innym miejscu.
andy
4
! Aby uruchomić skrypty Ruby Ruby% załatwi
Alexis Perrier
1
@andy:!%: p rozwiązuje również problem braku katalogu w $ PATH
MayTheSForceBeWithYou
2
I :!"%:p"radzić sobie z białymi znakami.
OJFord

Odpowiedzi:

109

Jest makepolecenie. Uruchamia polecenie ustawione w makeprgopcji. Użyj %jako symbolu zastępczego dla bieżącej nazwy pliku. Na przykład, jeśli edytujesz skrypt w języku Python:

:set makeprg=python\ %

Tak, musisz uciec z kosmosu. Następnie możesz po prostu uruchomić:

:make

Jeśli chcesz, możesz ustawić autowriteopcję, która zapisze się automatycznie przed uruchomieniem makeprg:

:set autowrite

To rozwiązuje część wykonawczą. Nie znam żadnego sposobu na przeniesienie tego wyjścia do podzielonego okna, które nie wymaga przekierowania do pliku.

R. Martinho Fernandes
źródło
5
W rzeczywistości Twoje rozwiązanie przenosi dane wyjściowe do podzielonego okna. Służy :copendo otwierania „listy błędów” utworzonej przez uruchomienie. W :makejego własnym oknie. Niestety, aby uzyskać poprawne sformatowanie danych wyjściowych, konieczne jest znalezienie tej errorformatopcji. W przeciwnym razie zakłada się, że wyjście ma format, jaki generuje gcc.
Conspicuous Compiler
2
Jesteś cholernie pewien co do "finagowania" formatu błędu. Wygląda jak jakiś kod perla, który widziałem ...
R. Martinho Fernandes
1
Ta funkcja jest dostępna dla 'tworzenia' projektu z vima (daje vimowi możliwości podobne do IDE). Rozwiązanie Briana Carpera ( :let f=expand("%")|vnew|execute '.!ruby "' . f . '"'), choć wygląda zagadkowo, działa dokładnie tak, jak zadał mu autor pytania.
AjayKumarBasuthkar
29

Aby uzyskać dostęp do nazwy pliku bieżącego bufora, użyj %. Aby umieścić go w zmiennej, możesz użyć expand()funkcji. Aby otworzyć nowe okno z nowym buforem, użyj :newlub :vnew. Aby przesłać dane wyjściowe polecenia do bieżącego buforu, użyj :.!. Kładąc wszystko razem:

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

oczywiście zastępując rubydowolną komendą. Użyłem, executewięc mogłem otoczyć nazwę pliku cudzysłowami, więc zadziała, jeśli nazwa pliku zawiera spacje.

Brian Carper
źródło
3
@baboonWorksFine Użyj, :command! R let f=expand("%")|vnew|execute '.!ruby "' . f . '"'aby móc po prostu użyć :Rdo wykonania jego polecenia
xorpaul
Czy byłoby możliwe, aby to działało nawet ze skryptami, które wymagają interwencji użytkownika podczas wykonywania?
ilstam
23

Vim ma polecenie !("bang"), które wykonuje polecenie powłoki bezpośrednio z okna VIM-a. Ponadto pozwala na uruchomienie sekwencji poleceń związanych z potokiem i odczytem stdout.

Na przykład:

! node %

jest równoznaczne z otwarciem okna wiersza poleceń i uruchomieniem poleceń:

cd my_current_directory 
node my_current_file

Zobacz "Wskazówki Vima: Praca z poleceniami zewnętrznymi" po szczegóły.

Gediminas Bukauskas
źródło
11

Mam do tego skrót w moim 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>

To zapisuje bieżący bufor, sprawia, że ​​bieżący plik jest wykonywalny (tylko unix), wykonuje go (tylko unix) i przekierowuje dane wyjściowe do .tmp.xyz, następnie tworzy nową kartę, odczytuje plik, a następnie usuwa go.

Rozbijając to:

: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
źródło
2
Twoje rozwiązanie bardzo mi się spodobało i po jakimś czasie korzystania z niego poczułem, że można je ulepszyć. Oto moje spojrzenie na to: :w<CR>:silent !chmod +x %:p<CR>:silent !%:p 2>&1 | tee ~/.vim/output<CR>:split ~/.vim/output<CR>:redraw!<CR>- przekierowuje zarówno stdout, jak i stderr do pliku tymczasowego, a zanim to zrobi, wypisuje wszystko na stdout, więc jeśli skrypt trwa długo, widać, że działa. Ponadto jest niezależny od katalogu (otrzymywałem błędy podczas otwierania plików według ich bezwzględnej ścieżki). Nie uruchamia jednak interaktywnie skryptów i nie znalazłem sposobu, aby to zrobić.
Kirill G
1
fyi - na rozwiązaniu @Cyril, musiałem uciec od symbolu rury: | -> \ |
mpettis
4

Użyłem skryptu Shell

:set makeprg=%

:make
Timur Fanshteyn
źródło
3

Vim 8 ma wbudowany interaktywny terminal. Aby uruchomić bieżący skrypt basha w podzielonym panelu:

:terminal bash %

lub w skrócie

:ter bash %

% rozwija się do bieżącej nazwy pliku.

Od :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
źródło
1

Używam nieco bardziej inwazyjnego mechanizmu poprzez mapy:

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

Po prostu sprawia, że ​​nie muszę zapisywać, a potem idź. Po prostu idź.

Jack M.
źródło
1
Jeśli ustawisz opcję autowrite, możesz uruchomić: make i it ... auto zapisuje wcześniej.
R. Martinho Fernandes
1

Możesz użyć wtyczki vima bexec . O ile mi wiadomo, najnowsza wersja to 0.5.

Następnie:

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

Wewnątrz samego vima podczas edycji pliku .vba wykonaj:

:so %

Pojawi się informacja, że bexec.vim został napisany, a także dokumentacja itp.

Teraz możesz to przetestować otwierając swój (dowolny skrypt językowy, który ma interpreter #! Działający poprawnie) w vimie i uruchom

:Bexec 

Uwaga: chciałem, aby podział był pionowy, a nie poziomy, więc zrobiłem:

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

i zmieniłem wartość z „hor” na „ver” ..

Wiem, że to stare pytanie, ale mam nadzieję, że może to komuś pomóc. Pracowałem w tym samym numerze podczas kursu Coursera Startup Engineering, na którym profesor Palaji używa Emacsa, a ja nie lubię Emacsa.

Angie
źródło
Powinieneś zmienić ustawienia związane z preferencjami w swoim lokalnym pliku .vimrc. bexec oferuje ustawienie „let bexec_splitdir = 'hor'”, które może to zrobić bez modyfikowania kodu wtyczki.
Saurabh Hirani
0

W oparciu o @SethKriticos i @Cyril Answers używam teraz następujących elementów:

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>

Użyj F9, aby skonfigurować nowe okno i F2, aby wykonać skrypt i tee w pliku wyjściowym.

Dodałem również nazwę skryptu do nazwy pliku wyjściowego, dzięki czemu można jej używać dla wielu skryptów w tym samym czasie.

xorpaul
źródło
0

W swoim .vimrcmożesz wkleić tę funkcję

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

Następnie jako przykład vimuruchom polecenie :shell python ~/p.py. Wynik otrzymasz w podzielonym oknie. + Po zmianach w p.pyprzykładzie uruchomisz ponownie to samo polecenie, ta funkcja nie utworzy ponownie nowego okna, wyświetli wynik w poprzednim (tym samym) podzielonym oknie.

Igor Komar
źródło
To jest niesamowite, dziękuję! Jak możesz to zmienić, aby uruchamiał się ponownie, gdy bufor zostanie ponownie zapisany?
elzi
0

@xorpaul

Szukałem tego skryptu (python / Windows) od jakiegoś czasu. Ponieważ w systemie Windows nie ma „trójnika”, zmieniłem go na:

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
źródło
0

Po prostu użyj dwukropka i wykrzyknika, jak pokazano poniżej

:! <nazwa_skryptu>

Sarath
źródło