вторник, 26 января 2021 г.

Полезные плагины для Vim - взгляд из прошлого

 

Как-то давным давно, я писал небольшие заметки о полезных плагинах для vim, для ныне почившего сайта. И вот недавно я наткнулся на эти статьи и решил их выложить.


vim-template - Шаблоны для различных типов файлов

Язык написания плагина: VimL

Зависимости: нет

Сегодня мы рассмотрим плагин добавляющий в vim шаблоны для типов файлов. Но сначала поговорим для чего нам всё это нужно. Во первых вас не утомляет писать по сути один и тот же код например при создании заголовочного (.h) файла? Писать include guards? Или другой пример, вы создаёте html страницу в vim, ищите откуда скопипастить начальную структуру документа (все эти html, head, body...) Не совсем удобно, правда? В любой IDE или маломальски приличном текстовом редакторе заготовки для различных типов файлом обычно идут из коробки стоит только перейти в меню File->New...

В vim так-же достаточно методов добавления вышеописанного функционала, начиная с abbreviations, заканчивая самописными функциями, стартующими при событии создания файла.

Однако для меня оказалось удобнее использовать плагин vim-template. Преимущества:

  • простой
  • легко расширяем

А теперь подробнее об использовании. После установки плагина, в директории $VIMRUNTIME создаём папку template, в ней и будут хранится наши заготовки для файлов. Вот структура моей директории template:

template:
|   template.c
|   template.cmd
|   template.cpp
|   template.h
|   template.htm
|   template.html
|   template.py
|   template.vnote
|   text.rst
|
+---plugin
|       template.vim
|
\---win32
        template.cpp

Для того чтобы плагин смог найти определённый темплейт, файлы должны называться template.*

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

С помощью события plugin-template-loaded плагин даёт нам понять, что пора раскрыть переменные находящаяся в темплейте, небольшой пример из моего vimrc:

augroup template-plugin
    autocmd User plugin-template-loaded call s:template_keywords()
augroup END

function! s:template_keywords()
    if search('<+FILE_NAME+>')
        silent %s/<+FILE_NAME+>/\=toupper(expand('%:t:r'))/g
    endif
    if search('<+CURSOR+>')
        execute 'normal! "_da>'
    endif
    silent %s/<+DATE+>/\=strftime('%Y-%m-%d')/g
endfunction

В функции s:template_keywords() мы определяем три переменные, думаю знатокам vim этот код предельно понятен, поэтому не буду останавливаться на нём подробнее. Вот таким нехитрым способом вы можете добавить свои переменные, а затем использовать их в шаблоне.

Так-как в вашей папке на данный момент пусто, пора добавить туда первую заготовку например для заголовочного файла языка C++:

template.h:

// created: <+DATE+>
#ifndef <+FILE_NAME+>_H_INCLUDED
#define <+FILE_NAME+>_H_INCLUDED

<+CURSOR+>

#endif // <+FILE_NAME+>_H_INCLUDED

Теперь, при открытии пустого .h файла, или создании через vim, командой :new, наш шаблон раскроется в такой код (для example.h):

// created: 2012-09-02
#ifndef EXAMPLE_H_INCLUDED
#define EXAMPLE_H_INCLUDED


#endif // EXAMPLE_H_INCLUDED

См. Также:

Справочный файл: :help template

Страница плагина на vim.org: http://www.vim.org/scripts/script.php?script_id=2834

Git-репозитарий: https://github.com/thinca/vim-template.git


CtrlP - нечёткий поиск по файлам, буферам, тегам, ...

Язык написания плагина: VimL

Зависимости: нет

Для vim существует огромное количество плагинов, как полезных так и не особо нужных. Но среди них есть и те, после использования которых, вы восклицаете - как я раньше жил без этого! Сегодня я познакомлю вас с одним из них, встречайте - CtrlP. Цель этого плагина сделать максимально удобным и быстрым поиск файлам, буферам, тегам, и т.д.

Основные возможности плагина:

  • Поиск по мере набора
  • Используется "нечёткий поиск" что позволяет найти цель вводом всего пары символов
  • Написан на чистом VimScript, одинаково хорошо работает для MacVim, gVim и Vim 7.0+
  • Полная поддержка регулярных выражений vim
  • Поддержка поиска по недавно открытым файлам (MRU) и по открытым буферам
  • Расширения, благодаря которым искать можно не только по файлам, но например, по тегам генерируемым ctags

Для начала немного о "нечётком поиске", предположим у нас есть директория вида:

kraken
|   buidldoc.cmd
|   kraken.py
|   readme.htm
|   readme.rst
|   tags
|   test.py
|
\---kraken_handlers
    |   base.py
    |   pdb_postmortem_loader.py
    |   pyqt4_error_reporter.py
    |   save_crash_info.py
    |   __init__.py

Для того чтобы открыть файл __init__.py в vim, вам придётся прописывать его полный путь: :o kraken/kraken_handlers/__init__.py это долго и утомительно. С помощью нечёткого поиска это делается вводом всего лишь части названия файла, например __ однозначно найдёт совпадение с файлом. Удобно так-же то, что по мере набора вы сразу видите результат.

Такой-же трюк можно проделывать и с директориями:

Используйте <c-p> или ``:CtrlP`` для вызова плагина

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

Совет: для того чтобы после открытия файла, сразу перейти к нужному номеру строки введите :<номер строки> после имени, пример: >>__i:10.

Плагин CtrlP не ограничивается поиском только по файловой системе, с помощью команд :CtrlPBuffer и :CtrlPMRU он позволяет искать по открытым буферам и недавно закрытым файлам соответственно. Но это ещё не всё, с помощью расширений плагина, он даёт возможность поиска по тегам, директориям, истории изменений и много чему еще, но об этом мы поговорим позже.

Сравнение с аналогами

Помимо рассматриваемого, для vim существует еще, по крайней мере два плагина с похожим функционалом это command-t и FuzzyFinder. И последним из них, я достаточно долго пользовался, пока не узнал о CtrlP. Причиной перехода стало то что FuzzyFinder давно не обновлялся и скорее всего, заброшен автором.

Command-t вдохновлялся TextMate, его авторы хвалятся скоростью работы плагина. Благодаря использованию Ruby и C-extensions к нему. Сам я этот плагин не ставил. Из-за вышеописанных зависимостей (для меня важна портабельность). Возможно, Ruby-программистам Command-t подойдёт больше.

Расширения

С помощью команд-расширений плагин позволяет искать:

  • CtrlPTag - по тегам, сгенерированным ctags
  • CtrlPBufTag - тегам внутри буфера
  • CtrlPQuickfix - буферу qucckfix
  • CtrlPDir - директориям
  • CtrlPRTS - файлам в runtime vim (vim-скрипты, файлы справки, снипеты)
  • CtrlPUndo - истории отмен (Undo history)
  • CtrlPLine - номерам строк файла
  • CtrlPChange - списку последних изменений файла
  • CtrlPMixed - сразу по файлам, буферам и списку последних открытых файлов

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

Включить расширения можно, перечислив их в переменной g:ctrlp_extensions:

let g:ctrlp_extensions = ['tag', 'buffertag', 'quickfix', 'dir', 'rtscript',
                        \ 'undo', 'line', 'changes', 'mixed', 'bookmarkdir']

См. Также:

Справочный файл: :h CtrlP

Страница на vim.org: https://github.com/kien/ctrlp.vim.git

Домашняя страница плагина: http://kien.github.com/ctrlp.vim/

Git-репозитарий:


FencView - открыть файл в нужной кодировке, легко!

Язык написания плагина: VimL

При работе в разных операционных системах и окружениях, возникает необходимость открывать файлы в различных кодикорвах (например cp1251 для Windows). Для задания кодировки файла в Vim существует команда fileencoding={enc}. Однако не всегда мы знаем исходную кодировку файла. В таком случае бывает удобнее попробовать несколько вероятных кандидатов из списка.

Планин fencview предоставляет нам эту возможность, добавляя в меню GVim пункт Tools->Encoding

Если-же вы пользуетесь консольной версией, то введите команду FencView

Команда FencAutoDetect пробует определить кодировку файла самостоятельно. К сожалению она заточена на определение языков восточной письменности (Chinese Simplified, Chinese Traditional, Japanese, Korean) и в наших краях не сильно полезна. По этой причине я бы советовал отключить автоопределение кодировки при открытии файла, опцией:

g:fencview_autodetect = 0

Зависимости

Плагин требует опцию +iconv для своей работы (проверить можно так :echo has('iconv')), а так-же библиотеку iconv.dll (если вы работаете в Windows), расположенную в %PATH% или рядом с исполняемым файлом Vim, как у меня.

Совет: с помощью встроенной опции Vim - fileencodings вы можете задать список кодировок, с помощью которых Vim будет пробовать открыть файл пример:

set fileencodings=ucs-bom,utf-8,cp1251

так-же для задания кодировки файлов по умолчанию используется опция fileencoding пример:

set fileencoding=utf-8

См. Также:

Страница плагина на vim.org: http://www.vim.org/scripts/script.php?script_id=1708


pyflakes - подсветка ошибок в коде python на лету

Язык написания плагина: VimL, python

Зависимости: +python

Часто ли вы делаете опечатки? Вот я частенько, бывает, даже когда я пишу в код. Это не так страшно, если вы пишете на языках со статической типизацией, например на C++ или Java, компилятор просто тыкает вас в место ошибки, при несоответствии типов или забытом параметре функции. А как быть при работе с интерпретируемыми ЯП?

Я много кода пишу на python и уже не представляю себе жизни без подсветки ошибок в редакторе на лету. В vim эту функцию выполняет плагин pyflakes-vim, основанный на утилите для проверки ошибок .. _pyflakes: https://github.com/kevinw/pyflakes Вся прелесть этой утилиты в том, что она не просто выявляет синтаксические ошибки, которые и так можно посмотреть, запустив скрипт. Но и показывает:

  • неиспользуемые импорты и переменные
  • использование переменной до её определения
  • переопределение функции/метода в локальной области видимости

Совет: Все найденные ошибки так-же отображаются в стандартном окне quickfix. Открыть которое можно командой ``:cwin``.

pyflakes vs Syntastic

Хотя сам автор плагина пишет что он deprecated и рекомендует переходить всем на .. _Syntastic: http://www.vim.org/scripts/script.php?script_id=2736 , так-как в этот плагин подсвечивает, в том числе и ошибки python'а. Я досих пор пользуюсь именно pyflakes-vim для python, просто потому что он для меня более удобен:

  • Подсвечивает ошибки сразу, а не при сохранении как Syntastic.
  • Сама подсветка реализована более правильно, вместо sings используется подсветка а-ля spellcheck.
  • Портабельность, всё необходимое для работы плагина лежит в его директории (кроме интерпретатора python разумеется)

Однако для других языков я использую Syntastic, в виду того что он поддерживает большое количество ЯП.

Для тех кому интересен Sytastic: http://habrahabr.ru/post/108564/

Замечание: плагин не поддерживает python 3+

См. Также:

Страница на vim.org: http://www.vim.org/scripts/script.php?script_id=2441

Git-репозитарий: https://github.com/kevinw/pyflakes-vim.git


tagbar - удобная навигация по всем функциям и классам

Язык написания плагина: VimL

Зависимости: ctags

Думаю, ни для кого не будет секретом, что когда кода становится много, искать что-либо в нём бывает затруднительно. Продвинутые редакторы кода и интегрированные среды разработки научились решать эту проблему с помощью так называемых outline`ов. Данный функционал представляет собой окно, со списком всех сущностей в коде (макросов, классов, функции и тд). Что позволяет сразу перейти к определению кликнув на нужный элемент.

В vim с давних пор для этого использовался плагин taglist, формировавший outline окно с помощью внешней утилиты ctags. Большим недостатком этого плагина было то что он структурировал сущности в виде списка, в то время как более привычным и наглядным является древовидное представление.

Какое то время назад мне на глаза попался плагин исправляющий недостатки taglist, имя ему tagbar:

Плагин отлично выполняет свою основную задачу, наглядно показывая сущности в коде. Так-же как и taglist, плагин использует утилиту ctags для получения информации из кода.

В завершение я хочу показать несколько полезных настроек плагина:

" Показывать окно слева
let g:tagbar_left = 1

" Ширина окна
let g:tagbar_width = 30

" Показывать стрелки вместо +/-
let g:tagbar_iconchars = ['▶', '◢']

" Не сортировать
let g:tagbar_sort = 0

См. Также:

Справочный файл: :help tagbar

Страница плагина на vim.org: http://www.vim.org/scripts/script.php?script_id=3465

Git-репозитарий: https://github.com/majutsushi/tagbar.git


vim-fswitch - быстрое переключение между заголовочным файлом и реализацией

Используемые языки при написании плагина: VimL

Зависимости: нет

Если вы пишете что-либо на С/С++ с используя Vim, то наверняка вам не хватает быстрого способа перейти от заголовочного файла к реализации (напр от foo.h к foo.cpp). Если вы задавались вопросом, почему нельзя реализовать такой простой функционал в самом редакторе, то ответом по моему мнению будет идеология. Vim != IDE, Vim это просто отличный текстовый редактор, ничего не знающий о семантике кода и системе сборки вашего проекта. Т.е. если упрощённо, откуда ему знать что заголовочные файлы вы держите в папке ./foo/include проекта? Но иногда удобство важнее идеологии и человек написавший плагин vim-fswitch со мной согласен.

a.vim VS vim-fswitch

Долгое время я писал на С++ простенькие утилиты для себя, чтобы быстро переключатся от заголовка к реализации использовался плагин a.vim. Но большой минус этого плагина в том что он не даёт возможности настроить пути для поиска файлов. Т.е. если .h файл не лежит рядом с .cpp файлом, он его просто не найдёт. Поискав на vim.org более функциональные альтернативы я наткнулся на vim-fswitch. Больше всего меня привлекла возможность гибкой настройки поиска файлов, на основе регулярных выражений.

Пример из моего vimrc:

augroup fswitch-autocommands
    au BufEnter *.cpp let b:fswitchdst  = 'h,hpp'
    au BufEnter *.cpp let b:fswitchlocs = './,./include/,../include,./inc'

    au BufEnter *.h let b:fswitchdst  = 'c,cpp'
    au BufEnter *.h let b:fswitchlocs = '../src,../,./'
augroup END

Тут мы ищем заголовочные (.h, .hpp) файлы в директориях ./include/, ../include, ./inc относительно нашего текущего буфера, а так-же в самой директории с файлом. Соответственно файлы реализации (.c, .cpp) в директориях ../src, ../ и текущей.

Из возможностей, так-же стоит отметить:

  • Создание пустого файла, если поиск ничего не дал, используя предпочитаемое расположение
  • Гибкость настройки путей для каждого буфера

Основные команды

Для простого переключения служит команда FSHere. Если вы предпочитаете видеть заголовочный файл и реализацию в одном окне, то для этого существует семейство команд которые открывают альтернативный файл, с рездлением текущего окна: FSSplitLeft (отобразить горизонтально слева), FSSplitRight (справа), FSSplitAbove (вертикально сверху), FSSplitBelow (снизу).

Совет:

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

Для того чтобы этот пункт отображался только для определённых типов файлов (С/C++) используется функция ToggleFTContextMenu:

function! ToggleFTContextMenu(languages, modifiers, menuitem, action)
    for lang_ in a:languages
        if &filetype != lang_
            execute 'silent! aunmenu ' . a:menuitem
            continue
        endif
        for modifier in a:modifiers
            let esc = ''
            if modifier == 'i'
                let esc = '<esc>'
            endif
            let command =  modifier . 'menu <silent> ' . a:menuitem . ' ' . esc .':call ' . a:action . '<cr>'
            execute command
        endfor
        return
    endfor
endfunction

Теперь осталось зарегистрировать наше меню хитрым способом:

augroup user-contextmenu
    au MenuPopup * call ToggleFTContextMenu(["cpp", "c"],["i","n"],
                \"PopUp.-Usrsep5-", ":")

    au MenuPopup * call ToggleFTContextMenu(["cpp", "c"],["i","n"],
                \"PopUp.Swtich\\ Header/Source", "FSwitch('%', '')")
augroup END

См. Также:

Справочный файл: :help fswitch

Страница плагина на vim.org: http://www.vim.org/scripts/script.php?script_id=2590

Git-репозитарий: https://github.com/derekwyatt/vim-fswitch.git


Комментариев нет:

Отправить комментарий