Как выполнить редактируемый файл в Vi (m)

103

Как запустить файл, который я редактирую в Vi (m), и получить вывод в разделенном окне (как в SciTE)?

Конечно, я мог бы выполнить это так:

:!scriptname

Но можно ли избежать написания имени скрипта и как получить вывод в разделенном окне, а не только в нижней части экрана?

Алексей Болотов
источник
21
:!% позволит вам не писать "имя сценария". Приведенные ниже решения лучше, но я подумал, что упомяну об этом, если вы решите:!% Достаточно хорошо.
задумались
11
Еще одно замечание: вы можете использовать%: p (вместо просто%) для ссылки на абсолютный путь к текущему файлу. Это может быть необходимо, если ваш текущий каталог находится в другом месте.
Энди
4
для запуска скриптов Ruby:! 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
Вы чертовски уверены в том, что формат ошибок "доигрывает". Похоже на какой-то код Perl, который я видел ...
Р. Мартиньо Фернандес
1
Эта возможность доступна для создания проекта из 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
Можно ли выполнить этот запуск даже со сценариями, требующими ввода данных пользователем во время выполнения?
ilstam
23

В Vim есть !команда ("bang"), которая выполняет команду оболочки непосредственно из окна 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
4

Для сценария Shell я использовал

:set makeprg=%

:make
Тимур Фанштейн
источник
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.
апостоль 3пол
источник
1

Я использую немного более навязчивый механизм через карты:

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

Просто сделай так, чтобы мне не пришлось экономить, и уходи. Просто иди.

Джек М.
источник
1
Если вы установите опцию автозаписи, вы можете запустить: make, и он ... автоматически сохранится раньше.
R. Martinho Fernandes
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 предлагает настройку «let 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, чтобы выполнить ваш сценарий и перейти к выходному файлу.

Я также добавил имя сценария к имени выходного файла, чтобы вы могли использовать его для нескольких сценариев одновременно.

Xorpaul
источник
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 01
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>
Jetrock
источник
0

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

:! <имя_сценария>

Сарат
источник
0

Я бы рекомендовал плагин quickrun . Настроить быстро и просто. Вот небольшая демонстрация: введите описание изображения здесь

TornaxO7
источник