Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

На главную -> MyLDP -> Электронные книги по ОС Linux
Назад Просто о Vim Вперед

Vim : Сценарии

Введение

Если вы хотите сделать какое-то ПО удобным для себя, скорее всего, вы будете менять различные настройки в программном обеспечении, в соответствии с вашим вкусом и потребностями. Что делать, если вы захотите большего? Например, выполнить какие-то действия в зависимости от уловия: «Если такая-то версия GUI, то использовать эту цветовую схему, а если версия другая, то другую цветовую схему»? Для этого нужны "сценарии". Сценарии, в основном, подразумевают использование языка, с помощью которого можно указать условия и действия и связать их в «сценарии».

Есть два метода использования скриптов в Vim — использовать встроенный в Vim скриптовый язык, или использовать полноценный язык программирования, такой как Python или Perl, которые имеют доступ к внутренним модулям Vim (нужно чтобы Vim был скомпилирован с этими опциями).

В этой главе потребуется некоторое знание основ программирования. Если у вас нет опыта программирования, вы все равно поймете, хотя изложение покажется слишком кратким. Если вы хотите научиться программированию, пожалуйста, обратитесь к моей другой бесплатной книге - A Byte of Python.

Есть два способа создания многоразовой функциональности в Vim - использование макросов и написание сценариев.

Макросы

Используя макрос, вы можете записать последовательность команд и затем повторять их в различных ситуациях.

Например, пусть вы имеете какой-то текст наподобие этого:

   tansen is the singer
   daswant is the painter
   todarmal is the financial wizard
   abul fazl is the historian
   birbal is the wazir

Здесь есть много чего исправлять.

1. Изменить первый символ предложения в верхний регистр.

2. Изменить 'is' на 'was'.

3. Изменить 'the' на 'a'.

4. Завершить предложение с "in Akbar's court."

Один из способов заключается в использовании серии команд замены, типа :s/^\\w/\\u\\0/, но это потребует 4 команды замены и будет не очень хорошо, если команда замены изменит части текста, которые мы не хотим менять.

Эффективней было бы использовать макросы.

1. Установите ваш курсор на первом символе первой строки: tansen is the singer

2. Наберите qa в нормальном режиме для начала записи макроса с именем a.

3. Наберите gUl для перевода первого символа в верхний регистр.

4. Наберите w для перехода к следующему слову.

5. Наберите cw для замены слова.

6. Наберите was.

7. Нажмите <Esc>.

8. Наберите w для переходу к следующему слову.

9. Наберите cw для замены слова.

10. Наберите a.

11. Нажмите <Esc>.

12. Наберите A для вставки текста в конец строки.

13. Наберите in Akbar's court.

14. Нажмите <Esc>.

15. Наберите q для завершения записи макроса.

Это выглядит как длительная процедура, но иногда это гораздо легче, чем создать какие-то сложные команды замены!

В конце процедуры, строка должна выглядеть следующим образом:

Tansen was a singer in Akbar's court.

Великолепно. Теперь, давайте применим это к другим строкам. Просто переместите курсор на первый символ второй строки и нажмите @a. Вуаля, строка должна изменится на следующее:

Daswant was a painter in Akbar's court.

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

Примечание: Если вы хотите просто повторить последнее действие, а не последовательность действий, нет необходимости использовать макросы, просто нажмите . ( клавишу с точкой).

Основы написания скриптов

Vim имеет встроенный скриптовый язык, используя который вы можете написать свои собственные скрипты для принятия решений, исполнять "do", и управлять текстом.

Действия

Как вы измените тему, то есть используемый Vim цвет? Просто выполните:

:colorscheme desert

Здесь я использую цветовую тему 'desert', которая, по случаю, моя любимая. Вы можете увидеть другие доступные темы, набрав :colorscheme и затем нажав клавишу <tab> для переключения доступных тем.

Что делать, если вы хотели узнать, сколько символов в текущей строке?

:echo strlen(getline("."))

Обратите внимание на имена 'strlen' и 'getline'. Это функции ("functions"). Функции - это части скриптов, уже написанные и с именами, чтобы мы могли использовать их снова и снова. Например, функция getline извлекает строку, а мы указываем какие строки извлекать, . (точка) означает текущую строку.

Мы передаем результат, возвращаемый функцией getline, в функцию strlen, которая подсчитывает количество символов в тексте, а затем мы передаем результат, возвращаемый функцией strlen, команде :echo, которая просто выводит результат. Обратите внимание, как информация передается в этой команде.

Строка strlen(getline(".")) называется выражением. Мы можем сохранять результаты такого выражения, используя переменные. Переменные делают то, что следует из их названия, — это имена, указывающие на значения, и значением может быть что угодно, то есть оно может меняться. Например, мы можем сохранить значение длины строки в переменной len:

:let len = strlen(getline("."))
:echo "We have" len "characters in this line."

Когда вы запустите код из второй строки этого текста, вы получите следующий результат:

We have 46 characters in this line.

Обратите внимание, мы можем использовать переменную в другом выражении. Возможности, которые вы получаете с помощью переменных, выражений и команд, поистине безграничны.

Vim различает разные типы переменных с помощью префиксов, таких как $ для переменных среды окружения, & для опций, и @ для регистров:

:echo $HOME
:echo &filetype
:echo @a

Смотри :help function-list , где указан большой список доступных функций.

Вы сами можете создать функцию следующим образом:

:function CurrentLineLength()
: let len = strlen(getline("."))
: return len
:endfunction

Теперь позиционируйте ваш курсор на любой строке и выполните следующую команду:

:echo CurrentLineLength()

Вы должны увидеть напечатанную цифру. Имена функций должны начинаться с символов в верхнем регистре (с заглавной буквы). Это чтобы различать встроенные функции, которые начинаются с символа в нижнем регистре, и определяемые пользователем функции, которые начинаются с заглавных букв.

Если вы хотите просто вызвать ("call") функцию для запуска, но не отображать её вывод, вы можете использовать

:call CurrentLineLength()

Ветвления

Предположим, вы хотите отобразить различные цветовые схемы в зависимости от того работает Vim в терминале или работает в GUI, т.е. вам нужен скрипт для принятия решения. Вы можете использовать следующее:

: if has("gui_running")

: colorscheme desert

:else

: colorscheme darkblue

:endif

Как это работает:

has() функция, которая используется для определения, поддерживается ли данная функция в установленном на компьютере Vim. Смотри :help feature-list для просмотра того, какие возможности доступны в Vim.

Оператор if проверяет данное условие. Если условие выполняется, мы предпринимаем определенные действия. Иначе ("else"), мы предпринимаем альтернативные действия.

Обратите внимание, что объявление if должно иметь соответствующий endif.

elseif также доступны, если вы хотите построить цепочку с несколькими условиями и действиями.

Циклы, начинающиеся с 'for' и 'while', также доступны в Vim:

:let i = 0

:while i < 5

: echo i

: let i += 1

:endwhile

Вывод:

   0
   1
   2
   3
   4

Используя встроенные функции Vim, то же можно записать так:

:for i in range(5)

: echo i

:endfor

range() это встроенная функция, используемая для генерации диапазона чисел. Смотри :help range() для детального описания.

структуры continue и break также доступны.

Структуры данных

Скрипты Vim также поддерживают списки и словари. Используя их, вы можете строить сложные структуры данных и программы.

	:let fruits = ['apple', 'mango', 'coconut']

	:echo fruits[0]
		" apple
	
	:echo len(fruits)
		" 3
	
	:call remove(fruits, 0)
	:echo fruits
		" ['mango', 'coconut']
	
	:call sort(fruits)
	:echo fruits
		" ['coconut', 'mango']
	
	:for fruit in fruits
	:	echo "I like" fruit
	:endfor
		" I like coconut
		" I like mango

Есть много доступных функций — смотри разделы 'List manipulation' и 'Dictionary manipulation' в :help function-list.

Создание скриптов в Vim

Сейчас мы напишем сценарий Vim, который можно загружать в Vim и выполнять по мере необходимости. Это отличается от создания внутренних сценариев, исполняемых сразу после написания.

Давайте решим простую задачу — перевести в верхний регистр первую букву каждого слова в выбранном диапазоне строк? Вариант использования прост - когда я пишу заголовки в тексте документа, они выглядят лучше, если они капитализированы, но я слишком ленив, чтобы делать это самому. Однако, я могу написать текст в нижнем регистре, а затем просто вызвать функцию капитализации.

Мы начнем с простого шаблона сценария. Сохраните следующий скрипт как файл capitalize.vim:

	" Vim global plugin for capitalizing first letter of each word
	" 		in the current line.
	" Last Change: 2008-11-21 Fri 08:23 AM IST
	" Maintainer: www.swaroopch.com/contact/ 
	" License: www.opensource.org/licenses/bsd-license.php 
	
	if exists("loaded_capitalize")
		finish
	endif
	let loaded_capitalize = 1 
	
	" TODO : The real functionality goes in here. 

Как это работает:

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

Есть 2-3 стандартных заголовка описания файла, таких как 'Последнее обновление:', который объясняет, как был изменен 'Разработчиком' старый сценарий, информация, как пользователи могут связаться с разработчиком сценария по поводу каких-либо проблем или, возможно, с благодарностью.

Заголовок 'Лицензия:' не обязателен, но очень рекомендуется. Скрипты Vim или плагины, которые вы напишете, могут использоваться многими людьми, так что укажите лицензию для скрипта. Соответственно, другие люди могут улучшить вашу работу, а это будет в свою очередь, вам на пользу.

Скрипт может быть загружен неоднократно. Например, если вы открываете два различных файла в одном Vim и оба они .html файлы, тогда Vim использует подсветку HTML-синтаксиса для обеих файлов. Чтобы избежать запуска одного и того же скрипта дважды и повторного рендеринга, мы используется защита, заключающаяся в проверке существования имени 'loaded_capitalize' и закрытия его, если сценарий был уже загружен.

Теперь, давайте приступим к написанию реального функционала.

Мы можем определить функцию, выполняющую преобразование — капитализировать первую букву каждого слова, поэтому мы можем назвать функцию Capitalize(). Поскольку функция будет работать в диапазоне строк, мы можем указать этот диапазон.

	" Vim global plugin for capitalizing first letter of each word
		" in the current line
	" Last Change: 2008-11-21 Fri 08:23 AM IST
	" Maintainer: www.swaroopch.com/contact/ 
	" License: www.opensource.org/licenses/bsd-license.php 

	" Make sure we run only once
	if exists("loaded_capitalize")
		finish
	endif
	let loaded_capitalize = 1

	" Capitalize the first letter of each word
	function Capitalize() range
		for line_number in range(a:firstline, a:lastline)
			let line_content = getline(line_number)
			" Luckily, the Vim manual had the solution already!
			" Refer ":help s%" and see 'Examples' section
			let line_content = substitute(line_content, "\\w\\+", "\\u\\0","g")
			call setline(line_number, line_content)
	endfor
endfunction

Как это работает:

a:firstline и a:lastline представляют собой аргументы функции, соответственно, начала и конца диапазона строк.

мы используем цикл 'for' для обработки каждой строки в диапазоне (выборка производится getline()).

мы используем функцию substitute() для обработки регулярных выражений поиска-и-замены в строках. Здесь мы определяем функцию для поиска слов, которая выглядит так: '\\w\\+', что означает слово (т.е. непрерывный набор символов, которые составляют слово).

После нахождения таких слов они будут конвертированы, как указывают опции \\u\\0 — где \\u означает, что первый символ, следующий за этой последовательностью, должен быть преобразован в верхний регистр, а \\0 указывает совпадение, найденное функцией поиска substitute(), которое соответствует словам. Как результат, первая буква каждого слова будет преобразована в верхний регистр.

Затем вызывается функция setline() для замены строки в Vim измененной строкой.

Для выполнения этой команды:

1. Откройте Vim и введите какой-то случайный текст, типа 'this is a test'.

2. Запустите :source capitalize.vim - где 'source' это файл, в котором находятся команды, которые передаются в Vim, как мы это делали раньше.

3. Запустите :call Capitalize().

4. Строка должна теперь выглядеть так 'This Is A Test'.

Запускать :call Capitalize() каждый раз может показаться довольно утомительно, так что мы можем назначить короткие клавиш, используя leaders:

	" Vim global plugin for capitalizing first letter of each word 
	" in the current line 
	" Last Change: 2008-11-21 Fri 08:23 AM IST 
	" Maintainer: www.swaroopch.com/contact/ 
	" License: www.opensource.org/licenses/bsd-license.php 

	" Make sure we run only once 
	if exists("loaded_capitalize") 
		finish
	endif
	let loaded_capitalize = 1

	" Refer ':help using-<Plug>'
	if !hasmapto('<Plug>Capitalize')
		map <unique> <Leader>c <Plug>Capitalize 
	endif
	noremap <unique> <script> <Plug>Capitalize <SID>Capitalize
	noremap <SID>Capitalize :call <SID>Capitalize()<CR> 

	" Capitalize the first letter of each word 
	function s:Capitalize() range 
		for line_number in range(a:firstline, a:lastline) 
			let line_content = getline(line_number) 
			" Luckily, the Vim manual had the solution already! 
			" Refer ":help s%" and see 'Examples' section 
			let line_content = substitute(line_content, "\\w\\+", "\\u\\0", "g")
			call setline(line_number, line_content)
		endfor
	endfunction

Мы должны изменить имя функции с простого 'Capitalize' на 's:Capitalize', чтобы показать, что функция является локальной в скрипте и не будет доступна глобально, потому что мы хотим избежать вмешательства в другие сценарии.

Мы используем команду map для определения комбинации клавиш.

Символ <Leader>, обычно обратная косая черта.

Теперь мы определим комбинацию клавиш <Leader>c (т.е. символ leader, а затем символ 'c') для некоторой функциональности.

Мы используем <Plug>Capitalize для описания функции Capitalize() внутри плагина, т.е. нашего скрипта.

Каждый скрипт имеет ID, который показывается <SID>-ом. Таким образом, мы можем отобразить команду <SID>Capitalize для вызова локальной функции Capitalize().

Итак, теперь можно повторить шаги, описанные ранее, чтобы проверить этот скрипт, но на этот раз вы можете запустить \\c для капитализации строк(и) вместо запуска :call Capitalize().

Последний набор шагов может показаться сложным, но это просто говорит о том, что есть много возможностей в создании скриптов Vim, и они могут делать сложные вещи.

Если что-то пойдет не так в ваших сценариях, вы можете использовать v:errmsg для просмотра последних сообщений о ошибках, которые подскажут, что пошло не так.

Примечание: вы можете использовать :help для поиска помощи по всем вопросам, которые мы обсуждали выше, от :help \\w до :help setline().

Использование внешних языков программирования

Многие люди не любят тратить время на изучение скриптового языка Vim и могут использовать языки программирования, которые они уже знают и создавать плагины для Vim на этих языках. Это возможно, поскольку Vim поддерживает скрипты, написанные на Python, Perl, Ruby и на многих других языках.

В этой главе мы рассмотрим, как можно просто подключить и использовать плагин, написанный на языке Python, но вы также просто можете использовать любой другой поддерживаемый язык.

Как уже упоминалось ранее, если вы заинтересованы в изучении языка Python, вы можете ознакомиться с моей другой бесплатной книгой «A Byte of Python», и для начала мы должны проверить, есть ли поддержка языка программирования Python в Vim.

:echo has("python")

Если функция вернула 1, мы можем продолжать, в противном случае вы должны установить Python на вашей машине и проверить возможность еще раз.

Предположим, что вы пишете сообщение в блоге. Блогер обычно хочет, чтобы как можно больше людей, насколько это возможно, прочитало его/её блог. Один из способов того, как люди находят такие статьи в блогах, так это с помощью запросов в поисковой системе. Итак, если вы собираетесь писать на какую-то тему (скажем 'C V Raman', известный индийский физик, который получил Нобелевскую премию за свою работу по рассеиванию света), вы будете использовать ключевые фразы, чтобы помочь разным людям найти ваш блог, когда они делают поиск в данном разделе. Например, если люди пытаются найти 'c v raman', они также найдут 'raman effect', так что вы можете захотеть упомянуть это в вашем блоге или статье.

Как мы найдем похожие фразы? Оказывается, что решение довольно простое, благодаря поисковику Yahoo!.

Во-первых, давайте поймем, как использовать Python для доступа к текущему тексту, который мы будем использовать для создания связанных фраз.

	" Vim plugin for looking up popular search queries related
		" to the current line 
	" Last Updated: 2008-11-21 Fri 08:36 AM IST
	" Maintainer: www.swaroopch.com/contact/ 
	" License: www.opensource.org/licenses/bsd-license.php 

	" Make sure we run only once 
	if exists("loaded_related") 
		finish
	endif
	let loaded_related = 1 

	" Look up Yahoo Search and show results to the user 
	function Related() 
	python <<EOF

	import vim 

	print 'Length of the current line is', len(vim.current.line) 

	EOF
	endfunction

Основной подход к написанию плагинов в интерпретируемых языках такой же, как и во встроенном языке сценариев.

Ключевым отличием является то, что мы должны передать интерпретатору Python код, который мы написали на языке Python. Это достигается с помощью EOF, как показано выше - весь текст от команды python <<EOF до команд EOF передается в интерпретатор Python.

Вы можете протестировать эту программу, открыв Vim отдельно и запустив :source related.vim, а затем запустив :call Related(). При этом должно быть выдано что-то вроде 'Length of the current line is 54'.

Теперь, давайте покажем реальную функциональность программы. Поиск в Yahoo! имеет так называемый запрос RelatedSuggestion, доступ к которому мы можем получить, используя службу web. Доступ к службе web можно получить, используя Python API, реализуемый Yahoo! Search pYsearch:

	" Vim plugin for looking up popular search queries related
	" to the current line 
	" Last Updated: 2008-11-21 Fri 08:36 AM IST
	" Maintainer: www.swaroopch.com/contact/ 
	" License: www.opensource.org/licenses/bsd-license.php

	" Make sure we run only once 
	if exists("loaded_related") 
		finish
	endif
	let loaded_related = 1 

	" Look up Yahoo Search and show results to the user 
	function Related() 
	python <<EOF

	import vim 
	from yahoo.search.web import RelatedSuggestion

	search = RelatedSuggestion(app_id='vimsearch', query=vim.current.line)

	results = search.parse_results() 

	msg = 'Related popular searches are:\n' 
	for i, result in enumerate(results):
		msg += '%d. %s\n' % (i + 1, result)
	print msg 

	EOF
	endfunction

Обратите внимание, что мы используем текущую строку в Vim как актуальный текст, который нас интересует, вы можете изменить текст на такой, какой вы захотите, например, текущее слово и т. д.

Мы используем класс yahoo.search.web.RelatedSuggestion для запроса в поисковике Yahoo! фраз, относящихся к запросу, который мы указали. Мы получим результаты, применив parse_results() к полученному объекту. Затем перебираем в цикле результаты и показываем их пользователю.

1. Запустите :source related.vim

2. Наберите текст c v raman.

3. Запустите :call Related()

4. Вывод должен показать нечто такое:

   Related popular searches are:
   1. raman effect
   2. c v raman india
   3. raman research institute
   4. chandrasekhara venkata raman

Итоги

Мы показали работу скриптов, используя внутренний язык скриптов Vim, а также используя внешние скриптовые языки/языки программирования. Это важно поскольку функциональность Vim может быть расширена до бесконечности.

Смотри :help eval, :help python-commands, :help perl-using и :help ruby-commands для получения более полной информации.

Внешние ссылки

http://developer.yahoo. com/search/web/V1/relatedSuggestion.html

http://pysearch.sourceforge.net



Предыдущий раздел: Следующий раздел:
Управление персональной информацией Оглавление Плагины