Одним из вариантов является непосредственное использование команды :normal!
, которая позволяет вам запускать последовательность нажатий клавиш так же, как если бы вы использовали их в сопоставлении.
Но это Оказывается, мы можем сделать лучше, намного лучше, так что давайте к этому!
Поиск и сопоставление
Вы можете использовать функцию search()
чтобы найти класс, в котором вы находитесь. Вы можете передать ему флаги, такие как bcnW
, чтобы он выполнял поиск b и наоборот, возможно, совпадет с c урсом Положение, n не перемещайте курсор и не w рэп вокруг файла. Собираем все вместе:
let line = search('^class \w', 'bcnW')
Это вернет номер строки, если было положительное совпадение, или 0, если его не было. Если совпадение было найдено, мы можем использовать getline()
, чтобы получить его содержимое, а затем matchlist()
, чтобы захватить имя класса.
let [_, classname; _] = matchlist(getline(line), '^class \(\w\+\)')
Как вы можете видеть, используя В Vimscript нам удалось получить имя класса, не перемещая курсор и не касаясь регистра поиска. Поэтому нам не нужно было ставить какие-либо отметки, и нам не нужно беспокоиться о восстановлении текущей позиции и вида!
Выполнение команды
Теперь пришло время запустить команду на Терминал. Мы можем упростить процесс, передав ему команду напрямую. (Обратите внимание, что здесь есть разница в том, что терминал будет запускать только этой команды, он не покинет оболочку после завершения. В зависимости от вашего варианта использования, вы можете предпочесть сделать что-то более похожее на что вы делаете сейчас.)
Мы можем запустить команду в терминале с помощью:
:terminal ++shell cd test && python testRunner.py MyTest1
Но, конечно, нам нужно передать ему имя класса, которое мы получили, здесь не фиксированное значение. Для этой цели мы можем использовать команду :execute
. Он берет строку и запускает ее как команду Vimscript. Мы можем использовать это для динамической сборки строки.
execute "terminal ++shell cd test && python testRunner.py ".shellescape(classname)
Наконец, чтобы go вернуться к исходному окну, мы можем использовать команду :wincmd
, более конкретно wincmd p
.
Собираем все вместе
Получаемая функция:
function! RunThisTest() abort
let line = search('^class \w', 'bcnW')
if line == 0
echoerr "Not inside a test class!"
return
endif
let [_, classname; _] = matchlist(getline(line), '^class \(\w\+\)')
execute "terminal ++shell cd test && python testRunner.py ".shellescape(classname)
wincmd p
endfunction
nnoremap <silent> <leader>t :call RunThisTest()<CR>
Определенно есть место для улучшений, но это должно помочь вам начать!
Сохранение и восстановление контекста
Мы не go добавили сохранение и восстановление контекста, так как в этом случае на самом деле ничего этого не нужно!
Если бы вы разрабатывали функции, использующие команды которые влияют на глобальный контекст, вы можете использовать Vimscript для его сохранения и восстановления.
Например, если вы собираетесь искать, вы можете сохранить регистр @/
и восстановить его после поиска:
let saved_search = @/
/class
let @/ = saved_search
Если вы собираетесь восстановить регистр, вы также можете сохранить и восстановить его. Например, @"
для регистра по умолчанию. Вам также следует сохранить регистр type , в котором записывается, было ли содержимое взято в символьном, линейном или блочном контексте.
let saved_register = getreg('"')
let saved_regtype = getregtype('"')
normal! y3W
let words = getreg('"')
call setreg('"', saved_register, saved_regtype)
Вы также можете сохранить текущий view , который включает позицию, в которой находится курсор, а также другие параметры окна, такие как первая отображаемая строка и столбец, чтобы вы могли полностью восстановить этот контекст. Подробнее см. Функции winsaveview()
и winrestview()
.
Управление терминалами
Существуют функции для управления терминалом, которые go далеко за пределы возможностей :terminal
.
Например, гораздо более богатый term_start()
позволяет запускать команду в виде списка и передавать параметры, такие как 'cwd'
, для запуска команды в другом каталоге.
Таким образом, мы могли бы упростить выполнение нашего теста с помощью:
call term_start(['python', 'testRunner.py', classname], {'cwd': 'test'})
Также имеется term_sendkeys()
, который можно использовать для отправки нажатий клавиш на Терминал. Например, если вы предпочитаете запускать оболочку и вызывать сценарий Python через оболочку:
let termbuf = term_start(&shell, {'cwd': 'test'})
call term_sendkeys(termbuf, "python testRunner.py ".shellescape(classname)."\r")
Вы также можете использовать term_getline(termbuf, '.')
, чтобы получить содержимое строки, в которой находится курсор в данный момент. Например, вы можете использовать это, чтобы определить, находится ли терминал в приглашении оболочки (строка заканчивается на $
и пробел) или все еще на выполнении тестового бегуна.
Наконец, вы можете даже иметь команда работает внутри терминала вызова Vim команды! Через специальные escape-последовательности он может вызывать экспортированные функции или просить Vim открыть файлы для редактирования. Подробнее см. :help terminal-api
.
Узнать больше
Это все очень аккуратно ... Но как я могу узнать больше?
Мой первый Настоятельно рекомендуется прочитать превосходную «Изучите Vimscript на нелегком пути» , написанную Стивом Ло sh. Он охватывает основы языка, как взаимодействовать с редактором (отображения, автокоманды, выражения отступов, типы файлов) и основы того, как собрать подключаемые модули Vim. Он также охватывает распространенные ошибки Vimscript и лучшие практики для написания надежного кода. Это необходимо, если вы хотите серьезно относиться к написанию сценариев Vim.
Второе предложение - прочитать отличную документацию, доступную через :help
! Немногие приложения так же хорошо документированы, как Vim, так что знание вашего справочного руководства может действительно помочь.
В-третьих, StackExchange. В частности, Vi & Vim SE , который посвящен этой теме. Там вы найдете не только отличные ответы, но и сможете задавать отличные вопросы. У вас будет также возможность видеть замечательные вопросы, удивляться, как их решать, и, возможно, попытаться написать ответ. (Лично, с тех пор, как я начал использовать Vi & Vim SE, мой Vim-foo значительно улучшился, и я могу считать себя почти экспертом.) Я настоятельно рекомендую это.
Наконец, попрактикуйтесь. Обычно требуется несколько попыток, чтобы получить что-то действительно правильное. Но тот факт, что среда довольно динамична c и гибка, позволяет экспериментировать. Вы можете набирать команды и экспериментировать с ними в самом редакторе, поэтому обычно вы быстро тестируете свой код и получаете его в процессе написания.