История эта началась с небольшого поста уважаемого
tengu-crow, в котором я откментировал, что тоже есть такие идеи и методы использования. Собственно для того, что бы понять о чем идет дальше речь, желательно прочесть то, о чем шла речь в том посте + коментарии мои и
tengu-crow + последующие его заметки и наши общие коментарии под общим названием в его ЖЖ
"Афигено большой файл" тут,
тут, и
тут. :) И так речь идет о фолдинге в vim по просьбе вышеупомянутого френда. :)
Я не являюсь сторонником использования русских терминов и абревиатур, как например НЖМД - накопитель на жестких магнитных дисках, вместо хард драйв или просто хард. И поэтому люблю использовать устоявшиеся английские словоформы, порой даже записанные русскими буквами. Они, как правило более лаконичны, емки и облегчают понимание с иностранными коллегами. Так что уж простите, но я буду применять в тексте не "складки", а английское "фолдинг".
Небольшое лирическое отступление.
Когда программисты пишут программы, то довольно удобно, что бы все функции были "свернуты", то есть мы видели только их заголовки, а внутрь попадали только тогда, когда нам это действительно надо. Это напоминает лист бумаги, часть которого сложена и как бы скрыта от глаз, но в любой момент ее можно развернуть и глянуть что внутри. Данный подход называется фолдингом. Фолднг в vim бывает 3-х видов:
- manual - ручной
- indent - большая величина отступа означает большую глубину складки
- expr - для определения складок используется выражение
- syntax - складки определяются в соответствии с правилами подсветки синтаксиса
- diff - специальный режим складок для отражения различий в файлах
- marker - складки определяются с помощью специальных маркеров в тексте
В нашем случае я попробовал использовать режим expr, так как из всех методов более всего подходили 3: expr, syntax и marker. С маркерным методом я пободался, но так и не смог заставить его работать так, как я хочу, поэтому я его забросил, во всяком случае пока. С синтаксисом я вообще пока не разбирался, хотя и надо бы. ;) Поэтому остался метод "регулярных выражений", которые я очень люблю еще с первого знакомства с perl. :)
Далее лирика, но уже без отступлений. ;)
И так, в нашем афигено большом файле есть темы и заметки. И очень не плохо было бы, сворачивать все наши записи, оставляя только заголовки от них. С методом мы уже определились. Так что поехали. Далее привожу не весь, но часть конфига, дабы не загружать повествование лишними деталями. Для тех, кто не в курсе, коментарии в конфигах vim начинаются со знака ковычек (").
vim ~/.vimrc
;)
Собственно исторически сложилось, что файл со всякими записями у меня назывался *.clipboard, поэтому для его открытия я и сделал функцию.
"вызываем функцию при открытии файла
autocmd BufEnter *.clipboard silent exe LoadClipboardFile()
"сама функция
function! LoadClipboardFile()
"покажем номера строк, люблю я так ;)
set number
"выберем метод фолдинга
set foldmethod=expr
"а тут самое интересное: вычисление фолдинга по маскам, но об этом позже
set foldexpr=getline(v:lnum)=~'=end=---$'?'s1':getline(v:lnum)=~'^---=====\\s'?'a1':-1
"заголовок, тоже опишу ниже
set foldtext=v:folddashes.substitute(getline(v:foldstart),'^---=====\\s\\\|\\s=====---$','','g')
"отступ от края, в котором будут показываться уровни фолдинга
set foldcolumn=3
"ну это чисто для вставки даты в текст по нажатию F2
map <F2> :r!date '+\%F \%H:\%M \%S s'<CR>
imap <F2> <Esc><F2>
"а это для создания новой записи по нажатию F4
map <F4> o---===== <Esc>zo<F2>kJA =====---<CR>---===== <F2>kJA =end=---<Esc>k^/=====-<CR>h
endfunction
И так каждая запись у меня имела вид:
---===== <дата опционально> тема =====---текст
---===== <дата опционально> тема =end=---Соотеветственно строка
foldexpr=getline(v:lnum)=~'=end=---$'?'s1':getline(v:lnum)=~'^---=====\\s'?'a1':-1
делает следующее:
- берем текущую строку (getline)
- если она оканчивается на '=end=---$', то возвращаем s1, что означает конец текущего фолда (знак =~ - означает если содержит)
- если нет, то оцениваем ее начало на наличие '^---=====\\s', и если так, то возвращаем начало нового фолда (a1)
- если же нет, то возвращаем -1, что значит, что уровень фолда не поменялся
Комбинация:
<условие>?<результат если верно>:<результат если ложно> я думаю известно многим программистам. ;) Так что тут все довольно понятно.
Далее делаем еще одну косметическую операцию, а именно надпись на фолде:
set foldtext=v:folddashes.substitute(getline(v:foldstart),'^---=====\\s\\\|\\s=====---$','','g')
Тут вообще практически все понятно: устанавливаем заголовок фолда как строку, взятую из начала фолда и удалив из нее "
---===== " - вначале и "
=====---" - в конце, что бы не мешали. ;)
Ну можно еще немного объяснить, как работает вставка новой записи, хотя там все просто - чисто последовательность команд vim-а:
map <F4> o---===== <Esc>zo<F2>kJA =====---<CR>---===== <F2>kJA =end=---<Esc>k^/=====-<CR>h
- o---===== - вводимновую строку, печатаем начало заголовка и выходим в командный режим
- zo - раскрываем фолд, ибо обнаружив начало, наш фолд схлопывается
- F2 - на ней у нас висит мап ввода даты. ;)
- Но дата вбилась строкой ниже! Поэтому поднимаемся обратно и присоединяем (J) следующую строку к нашей.
- A - начинаем в конце ее добивать окончание заголовка (=====---)
- - переход на новую строку
- Далее все повторяется для закрывающего заголовка (=end=---)
- k - поднимаемся вверх
- ^ - переходим в начало строки
- /=====- - ищем точку после даты на первом знаке равно
- И делаем шаг влево, что бы оказаться сразу же за введенной датой и быть готовыми вводить новый заголовок. :)
Если лень - то нажмем просто "o" и будем в новой строке вводить текст, в заголовке останется только дата. Если нет - то напишем текст, который и будет отображаться в заголовке фолдинга.
Свернутый файл выглядит так:

Развернутый:

И далее: