Як виконати файл, який я редагую у Vi (m)


101

Як виконати файл, який я редагую у Vi (m) та отримати вихід у розділеному вікні (як у SciTE)?

Звичайно, я міг би виконати це так:

:!scriptname

Але чи можна уникати написання імені скрипта і як отримати вихід у розділеному вікні, а не в нижній частині екрана?


21
:!% дозволить вам уникати написання "ім'я сценарію". Нижче наведені рішення є кращими, але я подумав, що я згадаю це у випадку, якщо ви вирішите:!% Досить добре.
переосмислити

11
Ще одна примітка, ви можете використовувати%: p (замість лише%) для позначення абсолютного шляху поточного файлу. Це може знадобитися, якщо ваш поточний каталог знаходиться десь в іншому місці.
Енді

4
запускати сценарії рубіну:! ruby% зробить трюк
Алексіс Пер'є

1
! @Andy:%: р також вирішує , не маючи каталог , перебуваючи в $ PATH
MayTheSForceBeWithYou

2
І :!"%:p"впоратися з пробілами.
OJFord

Відповіді:


109

Є makeкоманда. Він виконує команду, встановлену в makeprgопції. Використовувати %як заповнювач для поточного імені файлу. Наприклад, якщо ви редагували сценарій python:

:set makeprg=python\ %

Так, вам потрібно уникнути місця. Після цього ви можете просто запустити:

:make

Якщо ви хочете, ви можете встановити autowriteпараметр, і він автоматично збережеться перед запуском makeprg:

:set autowrite

Це вирішує частину виконання. Не знаєте жодного способу отримання цього виводу в розділене вікно, яке не передбачає перенаправлення на файл.


5
Насправді ваше рішення отримує вихід у розділене вікно. Використовуйте :copenдля відкриття "списку помилок", створеного за допомогою запуску :make.in власного вікна. На жаль, для правильного форматування виводу необхідне деяке доопрацювання errorformatпараметра. В іншому випадку вважається, що вихід буде у форматі, який видає gcc.
помітний компілятор

2
Ви прокляті впевнені в "фіналізації" формату помилок. Це схоже на якийсь код Perl, який я бачив ...
Р. Мартінхо Фернандес

1
Цей інструмент доступний для 'make' проекту з vim (надає vim IDE подібний потенціал). Рішення Брайана Карпера ( :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

Чи можна було б виконати цей запуск навіть із скриптами, які потребують введення користувача під час виконання?
ілстам

23

Vim має !команду ("баг"), яка виконує команду оболонки безпосередньо з вікна VIM. Крім того, це дозволяє запускати послідовність команд, які з'єднані з трубкою та зчитуванням stdout.

Наприклад:

! node %

еквівалентно відкриттю вікна командного рядка та командам запуску:

cd my_current_directory 
node my_current_file

Докладніше див. У розділі "Підказки Vim: Робота з зовнішніми командами" .


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 до тимчасового файлу, і, перш ніж це зробити, він друкує все для stdout, тому якщо сценарій триває багато часу, ви насправді бачите, що він працює. Крім того, це не залежно від каталогу (я отримував помилки під час відкриття файлів за їх абсолютним шляхом). Однак він не запускає сценарії в інтерактивному режимі, і я не знайшов способу зробити це так.
Кирило Г

1
fyi - на рішення @Cyril, мені довелося уникнути символу труби: | -> \ |
mpettis


3

Vim 8 має вбудований інтерактивний термінал. Для запуску поточного сценарію bash на розділеній панелі:

: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 ... автоматично зберігає раніше.
Р. Мартіньо Фернандес

1

Ви можете використовувати плагін vim bexec . Наскільки мені відомо, остання версія - 0,5.

Тоді:

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

Всередині самого vim під час редагування .vba-файлу виконайте:

:so %

З'явиться деякий вихід, який дозволяє вам знати, що bexec.vim написано, а також документація тощо.

Тепер ви можете перевірити це, відкривши свій (незалежно від мови скрипт, у якому інтерпретатор #! Працює належним чином) у 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, де професор Паладжі використовує Emacs, а мені не подобається Emacs.


Ви повинні змінити налаштування, пов’язані з налаштуваннями, у вашому локальному .vimrc. bexec пропонує налаштування "нехай bexec_splitdir = 'hor" ", яке може зробити це без зміни коду плагіна.
Саурабх Хірані

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запустіть команду :shell python ~/p.pyяк приклад. І ви отримаєте вихід у розділеному вікні. + Після зміни в p.pyприкладі ви знову запустите ту саму команду, ця функція знову не створить нове вікно, вона відобразить результат у попередньому (тому ж) розділеному вікні.


Це приголомшливо, дякую! Як ви можете змінити його на повторне повторне написання буфера?
elzi

0

@xorpaul

Я шукав цей сценарій (python / Windows) досить довгий час. Оскільки в 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

Просто використовуйте двокрапку та знак оклику, як показано нижче

:! <ім'я сценарію>


0

Я б порекомендував плагін Quickrun . Це швидко і просто налаштувати. Ось невеличка демонстрація: введіть тут опис зображення

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.