Пока Vim пишет код за Вас…

в 5:32, , рубрики: plugin, python, vim, vimscript, метки: , ,

Пока Vim пишет код за Вас…

Не буду долго распинаться на тему того, насколько велик и могуч Vim — это уже давно и достоверно известно. Кто-то даже утверждает, что «Практически любая строка латинских букв является синтаксически верной командой для vi».

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

Действующие лица

Собственно, их всего два — Vim и Python. Но взаимодействие этих компонент приводит к тысяче изменений и десяти тысячам превращений. И вот однажды, когда меня в очередной раз посетило желание перенести часть моей повседневной активности в Vim, я взялся за написание плагина для чтения постов с главной страницы reddit. Идея предельно проста — вытягивать список постов в json формате и отображать их в форматированном виде в буффере редактора. Ну и, конечно, эта задумка носила частично образовательный характер.

В качестве доступных вариантов для написания плагина существуют Vimscript, Python, Ruby. Не имею возможности сравнить их достоинства и недостатки, скажу лишь, что Python был выбран просто потому, что я с ним хорошо знаком.

Плагин: Начало

Самый простой плагин для Vim представляет собой файл с расширением *.vim — но лучше так не делать) Создадим директорию с плагином, которую разместим в .vim/bundle/ (используем vundle). Внутри заведем директорию plugin с исходниками и добавим строку Bundle 'vim-reddit'. После этих телодвижений плагин будет запускаться при старте Vim.

Основой плагина будет являться все же код, написанный на Vimscript (reddit.vim). В нем будут содержаться некоторые настройки, подсветка отображаемых постов, а также обертка для вызова Python кода. Вкратце расскажу об основных моментах и «правилах хорошего тона» (хотя я и сам их порой игнорирую).

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

if !has('python')
    echo "Error: Required vim compiled with +python"
    finish
endif

Затем необходимо проверить, не был ли загружен плагин повторно. Если нет — открыто заявляем миру о своем присутствии:

if exists('vim_reddit_module')
    finish
endif
let vim_reddit_module = 1

Python модуль

Затем начинается основное действо. Для начала, раскрою страшный секрет запуска кода на Python из Vimscript:

function! Reddit()

python << EOF
# some function
main()
EOF

endfunction

Внутри блока можно расслабиться, и вызвать пару питоновских библиотек) Создадим модуль reddit.py (__init__.py подразумевается), который будет выполнять всю работу по загрузке json. Но просто так подключить его не получится, т.к. питон не сможет найти этот модуль. Для выхода из этой трагичной ситуации можно добавить путь к модулю в sys.path:

import sys, vim
sys.path.append(vim.eval("expand('<sfile>:p:h')"))

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

from reddit import main
main()

Теперь плавно перейдем к тому безобразию, которое происходит в reddit.main(). Опять же, пропущу никому неинтересные подробности загрузки json и сразу пройдусь по особенностям. А из особенностей здесь, пожалуй, только работа с буффером. Дело в том, что текущий буффер, в который будем добавлять загруженные посты, представляет собой простой массив строк. Поэтому, очистка выглядит вот так:

del vim.current.buffer[:]

а добавление строки вот так:

vim.current.buffer[0] = "Reddit front page ☢"
vim.current.buffer.append(20*"=" + " ☢")

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

Немного о мелочах

Чтобы сделать чтение более приятным, я добавил несколько полезных деталей:

setlocal nomodifiable
setlocal buftype=nofile
call s:reddit_syntax()

В качестве результата имеем нередактируемый буффер. Функция reddit_syntax раскрашивает содержимое во все цвета радуги. Она была подсмотрена вот здесь, за исключением одной группы, которую я добавил исключительно для себя:

syntax match title /^.{-1,} ☢/
highlight title gui=bold guifg=yellowgreen

Группа называется title и описывается соответствующей регуляркой, а затем выделяется bold шрифтом.

Заключение

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

Код плагина выложен в моем репозитории, его чрезвычайно просто установить с помощью vundle.

P.S.: Оказывается, утренние посты даются гораздо сложнее)

Автор: erthalion

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js