Очередную рубрику в Одиночной палате решено начать на Хабре, так как дожидаться адекватного отображения исходного кода на Дзене не представляется возможным (неужели это так сложно). А в этой рубрике без примеров кода, судя по всему, никак.
Речь в рубрике пойдет о работе в текстовом редакторе (Neo)Vim в качестве разработчика и, местами, графомана. Но не в традиционных форматах хвалебных од, рейтингов лучших плагинов, пятиминутных гайдов или хауту, а в формате неких мемуаров что-ли. От лица начинающего, а затем и более продвинутого, пользователя - часто от первого лица. Так как считаю, что категорически не хватает именно чего-то среднего, чуть более применимого в реальной жизни и работе, чем ролики в ютубе с пересказами "Getting started with..." на разный манер, и чуть менее объемного и перегруженного чем полные руководства. Так же крайне мало информации конкретно для русскоязычных пользователей и особенностях работы с раскладками отличными от латиницы.
Так же следует оговориться сразу, что здесь я не преследую цель максимально точно и достоверно расписать конкретные команды, сценарии и тонкости, так как проекты связанные с Vim, и уж тем более с NeoVim, развиваются в последнее время очень динамично и то, что кажется актуальным сегодня может оказаться устаревшей информацией и введением читателя в заблуждение уже завтра. Я постараюсь, конечно, упоминать используемые лично мной версии самих редакторов и плагинов к ним, но также попробую построить материал таким образом, что бы какие-то частности являлись лишь демонстрацией к более общим и менее подверженным устареванию приемам и понятиям.
Касательно того какому читателю будет адресована рубрика. Ну, во-первых, для тех кто умеет выходить из Vim. Это минимальное требование. Во-вторых, это будут статьи в контексте программирования и набора лонгридов, как, например, этот. Те кто использует редактор в качестве необходимого зла для эпизодического редактирования конфигурации сервера вряд ли найдут для себя здесь что-то полезное. Для тех, кто решил не просто запомнить стандартный набор сочетаний клавиш, а более менее серьезно решил остановить свой выбор на этом редакторе и принимает саму философию что-ли. Философию не только модального режима, макросов и повышения эффективности набора текста, но и более продвинутые вещи как самостоятельная детальная настройка. Для тех, кто не чурается того, что бы залезть в исходные коды плагинов, или даже того, что бы написать пару собственных.
Более того, поскольку я и сам не являюсь экспертом в большинстве сценариев использования, материалы будут сильно в контексте моих собственных нужд и способов применения. Например, мне лично от редактора нужно, что бы он очень хорошо интегрировался с базами данных. Кому-то это возможно не пригодится никогда. А если и пригодится не в той мере как мне. Языки программирования я буду использовать только хорошо знакомые мне, с которыми я сам работаю. Пока это в основном Java, PHP, PL/SQL, возможно, совсем немного из мира JavaScript. Кстати сказать, как-раз материалов использования Vim в качестве редактора для фронт-энд разработки предостаточно, а вот для беков значительно меньше. Вообще с самого начала обнаружилось, что наиболее популярные плагины не очень-то и хорошо работают как-раз с базами, в связи с чем, собственно, и возникло жгучее желание поделиться собственным опытом.
Еще считаю необходимым отметить, что я не радикал, которому надо во что бы то ни стало перенастроить и поменять всё на свете. При этом я не сторонник чьих-то готовых комбайнов всё-в-одном, потому что функции, которые мне не пригодятся никогда или я до них не еще не дорос сам, я считаю только мешают. Только то что необходимо - только хардкор. Например, если голый Vim и так неплохо справляется с какой-то функцией, типа проверки правописания или автодополнения дополнения пути, то я не ставлю для этого, может быть даже более симпатичный плагин. Или, например, раз уж комбинация <C-a>
изначально завязана на инкремент, то я не переназначаю её на выделение всего буфера, так это работало бы в другом графическом редакторе.
Говоря о графических редакторах. Я так же не противник графических редакторов текста. Я не преследую такую цель, что бы Vim был категорически консольным или работал исключительно без использования мыши. Хотя она тут действительно не сильно то и когда нужна. Если у вас по какой-то причине установлен GVim или аналог, то это совершенно нормально. Важна именно концепция. Это, наверное, все оговорки которые пришли мне в голову на данный момент, но не исключено, что я буду и впредь вносить какие-то общие пояснения.
Итак, давайте же, для общей затравки, придем к общему знаменателю и пробежимся по основным версиям и настройкам с которыми я работаю, что бы в будущем не возвращаться к этому и что бы мне считать, что у читателя либо основной редактор настроен примерно так же как и у меня, либо читатель понимает в чем отличия его конфигурации от моей.
Версии
Прямо сейчас у меня в распоряжении VIM - Vi IMproved 8.2 (2019 Dec 12, собрано Sep 13 2022 09:35:02)
Заплатки: 1-3995, 4563, 4646, 4774, 4895, 4899, 4901, 4919. Со стандартным набором опций сборки. Так же я попутно буду адаптировать NeoVim NVIM v0.8.1 Build type: Release LuaJIT 2.1.0-beta3. Важное из окружения это операционная система Kubuntu 22.04.1 LTS Jammy Jellyfish на Plasma 5.
Железо разное, в том числе мощное рабочее на серверах, минимальное на веб-хостинге, ну домашнее посредственное: на Intel i3-2120 c 16 GB RAM. Механических дисков не осталось ни где. Не то что бы это очень важно, но, например, от этого может зависеть скорость загрузки словарей автодополнения для баз данных. Версии ОС, прочих сопутствующих программ и редакторов при этом почти везде плюс-минус одинаковые, потому что конфигурацию я пытаюсь поддерживать кросс-системную, так что бы редактор у меня работал везде одинаково. (В частности лично я предпочитаю всё-таки исходную консольную версию, а не графическую только поэтому). От винды я в итоге ушел полностью, а маков никогда не было и, по-видимому, уже и не будет, поэтому приделывать всякие костыли для ваших систем, дорогие читатели почитатели проприетарщины извольте самостоятельно.
Версии сопутствующих программ тоже отчасти имеют значение. У меня это в среднем NodeJS 16-18, Python 3 и OpenJDK 17.
Языки программирования исходные коды на которых будут выступать предметом редактирования это, как я уже и упоминал выше, PHP >=7.4+, >=8.1, Java ~17, ну и SQL в принципе не очень важно какой, но акцент будет делаться на диалекте Oracle 12.1+ вместе с PL/SQL так как он мне нужен по работе.
На версиях плагинов и LSP серверов останавливаться здесь особенного смысла, думаю, нет, но в процессе возможно и они будут упомянуты там где это важно.
Если это кому-то интересно, темы везде темные. Система на Breeze GTK, эмулятор терминала konsole breeze dark, оболочка ZSH (oh-my-zsh) agnoster, vim/neovim +airline пока на sonokai andromeda. Но как вы понимаете это не постоянно. Плюс-минус то что будет мелькать на скриншотах. Да, в качестве файлового менеджера у меня чуть подшаманенный far2l, о котором могу отдельно рассказать, если это, опять же, кому-то интересно.
Базовая настройка
Вкратце по настройкам. Тут важно понимать, что это вещи очень индивидуальные и я абсолютно не настаиваю ни на одной из них как на необходимой или единственно верной. Заголовок /.vimrc
scriptencoding utf-8
set encoding=utf-8
set termguicolors
set nocompatible " Forget old vi
set showcmd " Show (partial) command in status line.
set showmatch " Show matching brackets.
set ignorecase " Do case insensitive matching
set smartcase " Do smart case matching
set incsearch " Incremental search
set autowrite " Automatically save before commands like :next and :make
set hidden " Hide buffers when they are abandoned
set mouse=a " Enable mouse usage (all modes)
set number
set relativenumber
set tabstop=4 " a tab is four spaces
set softtabstop=4 " when hitting <BS>, pretend like a tab is removed, even if spaces
set noexpandtab " don't expand tabs to spaces by default
set shiftwidth=4 " number of spaces to use for autoindenting
set shiftround " use multiple of shiftwidth when indenting with '<' and '>'
set backspace=indent,eol,start " allow backspacing over everything in insert mode
set autoindent " always set autoindenting on
set copyindent " copy the previous indentation on autoindenting
" white space characters
set nolist
" compatible space chars
set listchars=eol:$,tab:.\ ,trail:.,extends:>,precedes:<,nbsp:_
" incompatible with debian stretch
"set listchars=eol:↓,tab:\ \ ┊,trail:●,extends:…,precedes:…,space:·
highlight SpecialKey term=standout ctermfg=darkgray guifg=darkgray
" display white space characters with F3
nnoremap <F3> :set list! list?<CR>
let mapleader = " " " map leader to Space
" no indent on paste
set pastetoggle=<F2>
nnoremap <F2> :set invpaste paste?<CR>
set pastetoggle=<F2>
set noshowmode " duplicated by status line plugin
syntax enable
filetype on " required
" soft wrap
set wrap
set linebreak
Про кодировки, думаю, всё понятно: utf. Из специфических: termguicolors
берет цветовую палитру из эмулятора терминала. nocompatible
делает Vim обратно не совместимым со старым Vi, что вряд ли нынче кому-то необходимо. Показывать команды, скобки, надеюсь понятно,... включить мышь... relativenumber
интересная настройка, показывающая номера строк относительно курсора - мне зашло так. Отступы так же понятны и уж точно индивидуальны. Просто ставьте как вам угодно. Единственное могу сказать, забегая немного вперед, что их можно настроить индивидуально для типа файла. На listchars
не стоит обращать внимания совсем, так как комментарии здесь связаны с использованием в AstraLinux, a SpecialKey
делает почти невидимыми (в моей цветовой схеме) управляющие символы. А о привязках кнопок поговорим отдельно в одной из следующих статей цикла.
В конце syntax enable
и filetype on
включает подсветку синтаксиса и включает встроенный плагин, позволяющий создавать индивидуальные конфигурации для каждого типа файла в отдельности. В том числе включать и выключать подсветку. А вот с мягким переносом строк не всё так просто. Если ваша задача ограничивать длину строк исходного код программ до 80 символов, то такая настройка вам незачем. Однако, если вы временами не брезгуете написанием статеек или расписываете в комментариях сложные интерфейсы, то как-то переносить слова по строкам придется. Но из-за этого ломается навигация по строкам. Это я тоже разберу когда речь зайдет о горячих клавишах.
Для NeoVim и Lua примерно то же самое выглядит следующим образом ~/.config/nvim/lua/core/options.lua:
local opt = vim.opt
-- line number
opt.relativenumber = true
opt.number = true
-- tabs & indentation
opt.tabstop = 4 -- 4 spaces for tabs (prettier default)
opt.shiftwidth = 4 -- 4 spaces for indent width
opt.expandtab = true -- expand tab to spaces
opt.autoindent = true -- copy indent from current line when starting new one
-- line wrapping
opt.wrap = true -- disable line wrapping
opt.linebreak = true
-- search settings
opt.ignorecase = true -- ignore case when searching
opt.smartcase = true -- if you include mixed case in your search, assumes you want case-sensitive
-- cursor line
opt.cursorline = true -- highlight the current cursor line
-- appearance
-- turn on termguicolors for nightfly colorscheme to work
-- (have to use iterm2 or any other true color terminal)
opt.termguicolors = true
opt.background = "dark" -- colorschemes that can be light or dark will be made dark
opt.signcolumn = "yes" -- show sign column so that text doesn't shift
-- backspace
opt.backspace = "indent,eol,start" -- allow backspace on indent, end of line or insert mode start position
Должен попросить прощения заранее, что конфигурации пока не выложены в отдельный доступный репозиторий, но как только речь зайдет о более серьезных вещах обещаю это всё причесать и разложить по полочкам на гитхабе.
Раскладка и правописание
С раскладкой и проверкой правописания история отдельная. В целом я уже касался этой проблемы в основном своем бложике тем не менее появились уже и к этому небольшие дополнения. Во-первых, надо сказать, что худо-бедно к одновременно двум вариантом смены раскладки клавиатуры привыкнуть таки можно. По крайней мере сейчас я не испытываю чуть ли физической боли от того что надо всё время помнить где переключать. Моя версия выхода из положения, когда в Vim приходится набирать текст то по-русски то на латыни такой:
set keymap=russian-jcukenwin
set iminsert=0 " Чтобы при старте ввод был на английском, а не русском (start > i)
set imsearch=0 " Чтобы при старте поиск был на английском, а не русском (start > /)
Отдельно для Lua соответствующих команд я пока не обнаружил, так что выполняем как есть:
local cmd = vim.cmd
-- Русский язык
cmd("set keymap=russian-jcukenwin")
cmd("set iminsert=0")
cmd("set imsearch=0")
При этом я намеренно не стал менять переключение с <C-^>
(а оно по началу очень неудобное), на что-то другое, что бы не теряться в sudo
режиме или в "гостях".
Словарик для русского языка то загружается автоматически, то по каким-то, известным одному господу, причинам приходится таскать его с сайта OpenOffice и воспользовавшись командой :mkspell
по соответствующей инструкции создавать их самостоятельно. И то и другое в итоге работает, а если возникли трудности, отметьте это в комментариях к статье и я вспомню и распишу процесс чуть подробнее.
Существует еще одна небольшая проблема с добавлением сочетания для выхода в нормальный режим, но думаю это не так серьезно. Это когда в разных иностранных источниках говорится о том, что удобно привязать сочетание, к примеру, kj
или ii
на <ESC>
(:noremap kj <ESC>
). Дело в том, что если в английском языке сочетания этих букв в жизни практически не встречаются, то в русском языке что "дл" или "жд" или даже "эж" и "шш" достаточно распространенные и нужные последовательности. Вообще оказалось очень сложно подобрать что-то удобоваримое. Я остановился на "\э", что на латыни "'" (и уже может испортить жизнь там где очень много надо экранировать апостроф). А надо это, что бы не переключая раскладку уходить в нормальный режим. Поэтому вот. Можно конечно вообще не заморачиваться и жить с родным <ESC>
, но сочетание под рукой действительно несколько удобнее.
" esc in insert & visual mode
inoremap \' <esc>
vnoremap \' <esc>
inoremap \э <esc>
vnoremap \э <esc>
" change ins toggle
inoremap <Insert> <Esc>
То же самое для NeoVim:
local keymap = vim.keymap
-- use jk to exit insert mode
keymap.set({ "v", "i" }, "\\'", "<ESC>")
keymap.set({ "v", "i" }, "\\э", "<ESC>")
-- unbind ins toggle
keymap.set("i", "<Ins>", "<ESC>")
Так же, если вы обратили внимание, я отключил назойливую функцию переключения режимов вставки при помощи клавиши <Ins>
. Не знаю, может только мне одному, но она очень сильно мешает и режим ввода каким-то образом постоянно меняется на замену. Это очень раздражает. Но это я немного уже залез в следующий, более предметный разговор о горячих клавишах в Vim в других редакторах в терминале и в целом при работе в запредельных темпах.
:wq
mpa4b
Забавно, что 'категорически консольный' Vim в каком-нибудь графическом эмуляторе терминала в иксах на самом деле только добавляет ненужных слоёв обработки событий и отрисовки. Ну например, события от мышек и клавиатур собираются иксами и форвардятся в окошко эмулятора терминала. Там они преобразуются в ESC-последовательности и отдаются в консольный вим. Далее тот обратно отдаёт что печатать, терминал это расшифровывает и превращает в команды отрисовки буковок для иксов.
В то время как в графическом виме вот этой вот прослойки в виде эмулятора терминала вовсе нет -- Gvim сам получает события от иксов и им же говорит, что рисовать.