как выполнить файл, который я редактирую в vi (m)

<p>как выполнить файл, который я редактирую в vi (m) и получить вывод в разделенном окне (как в scite)?</p><p>конечно, я мог бы выполнить это так:</p><pre><code>:!scriptname </code></pre><p>но возможно ли избежать написания имени сценария и как получить вывод в разделенном окне вместо нижней части экрана?</p>

<p>существует команда <code>make</code>. он запускает команду, установленную в опции <code>makeprg</code>. используйте <code>%</code> в качестве заполнителя для текущего имени файла. например, если вы редактировали скрипт python:</p><pre><code>:set makeprg=python\ % </code></pre><p>да, вам нужно сбежать из космоса. после этого вы можете просто запустить:</p><pre><code>:make </code></pre><p>при желании вы можете установить параметр <code>autowrite</code>, и он будет автоматически сохранен перед запуском <code>makeprg</code>:</p><pre><code>:set autowrite </code></pre><p>это решает часть выполнения. не знаю никакого способа получить этот вывод в разделенное окно, которое не включает перенаправление в файл.</p>

<p>чтобы получить доступ к имени файла текущего буфера, используйте <code>%</code>. чтобы получить его в переменную, вы можете использовать функцию <code>expand()</code>. чтобы открыть новое окно с новым буфером, используйте <code>:new</code> или <code>:vnew</code>. чтобы передать вывод команды из текущего буфера, используйте <code>:.!</code>. собираем все вместе:</p><pre><code>:let f=expand("%")|vnew|execute '.!ruby "' . f . '"' </code></pre><p>очевидно, заменив <code>ruby</code> на любую команду, которую вы хотите. я использовал <code>execute</code>, чтобы заключить имя файла в кавычки, чтобы оно работало, если в имени файла есть пробелы.</p>

<p>vim имеет команду <code>!</code> ("bang"), которая выполняет команду shell непосредственно из окна vim. кроме того, он позволяет запускать последовательность команд, связанных с конвейером и считывать стандартный вывод.</p><p>например:</p><pre><code>! node % </code></pre><p>эквивалентно открытию окна командной строки и запуску команд:</p><pre><code>cd my\_current\_directory node my\_current\_file </code></pre><p>смотрите <a href="https://www.linux.com/learn/tutorials/442419-vim-tips-working-with-external-commands">"советы vim: работа с внешними командами"</a> для деталей.</p>

<p>у меня есть ярлык для этого в моем vimrc:</p><pre><code>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> </code></pre><p>это записывает текущий буфер, делает текущий файл исполняемым (только для unix), выполняет его (только для unix) и перенаправляет вывод в .tmp.xyz, затем создает новую вкладку, читает файл и затем удаляет его.</p><p>разбивая это:</p><pre><code>: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 </code></pre>

<p>для сценария shell я использовал</p><pre><code>:set makeprg=% :make </code></pre>

<p>vim 8 имеет встроенный интерактивный терминал. чтобы запустить текущий скрипт bash в разделенной панели:</p><pre><code>:terminal bash % </code></pre><p>или для краткости</p><pre><code>:ter bash % </code></pre><p><code>%</code> расширяется до текущего имени файла.</p><p>от <code>:help terminal</code>:</p><pre><code>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. </code></pre>

<p>вы можете использовать плагин vim <a href="http://www.vim.org/scripts/script.php?script\_id=1788">bexec</a> . насколько мне известно, последняя версия - 0.5.</p><p>затем:</p><pre><code>$ mkdir -p ~/.vim/plugin $ mv bexec-0.5.vba ~/.vim/plugin $ vim ~/.vim/plugin/bexec-0.5.vba внутри самого vim при редактировании файла .vba выполните::so % появится некоторый вывод, сообщающий, что <strong> bexec.vim </strong> был написан вместе с документацией и т.д.теперь вы можете проверить его, открыв (независимо от того, какой языковой скрипт с интерпретатором #! работает правильно) в 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] </code></pre><p>и изменил значение с "hor" на "ver" ..</p><p>я знаю, что это старый вопрос, но я надеюсь, что это может помочь кому-то там. я работал над тем же вопросом, проходя курс coursera по разработке стартапов, где профессор palaji использует emacs, а мне не нравятся emacs.</p>

<p>я использую немного более навязчивый механизм через карты:</p><pre><code>map ;e :w<cr>:exe ":!python " . getreg("%") . "" <cr> </code></pre><p>просто сделай так, чтобы мне не пришлось спасать, а потом уходи. просто иди.</p>

<p>@xorpaul</p><p>я долго искал этот скрипт (python/windows). поскольку в windows нет "тройника", я изменил его на:</p><pre><code>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> </code></pre>

<p>основываясь на ответах @sethkriticos и @cyril, я теперь использую следующее:</p><pre><code>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> </code></pre><p>используйте f9 для настройки нового окна и f2 для выполнения вашего скрипта и перехода к выходному файлу.</p><p>я также добавил имя сценария к имени выходного файла, чтобы вы могли использовать его для нескольких сценариев одновременно.</p>

<p>в вашем <code>.vimrc</code> вы можете вставить эту функцию</p><pre><code>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 </code></pre><p>после этого в <code>vim</code> запустите команду <code>:shell python ~/p.py</code> в качестве примера. и вы получите вывод в разбитом окне. + после изменений в <code>p.py</code> в качестве примера вы снова запустите ту же команду, эта функция больше не будет создавать новое окно, она отобразит результат в предыдущем (том же) разделенном окне.</p>