октября 16, 2011

Вставка кода с подсветкой в блог при помощи вима

Уже не первый год я вставляю сюда фрагменты кода. Для того, чтобы сгенерировать код с подсветкой, я использую команду :TOhtml вима, которая генерирует html-код с подсветкой текущего файла или выделенного фрагмента. Код html появляется в отдельном окне, содержит теги head и body, содержит теги br, которые здесь в блоггере не нужны, содержит кучу лишних переносов строк.

Поэтому создание кода с подсветкой занимало у меня некоторое время: сгенерировать, выполнить команду для удаления тегов br, удалить ненужные переносы строк, выделить фрагмент html-кода без тегов head, body, скопировать, закрыть окно, и, наконец, вставить html в нужное место.

Сегодня мне это окончательно надоело, и я автоматизировал этот процесс, сведя всё к одной кнопке.



Собственно, писать особо не о чем, приведу фрагменты кода, которые я разместил в свой _vimrc файл:
fun! Code(line1, line2)
        " Исполняем встроенную команду TOhtml
        " Она создаст в отдельном окне код html-странички
        exec a:line1.','.a:line2.'TOhtml'
        " Удаляет всё, что находится выше строки, которая содержит <body
        %g/<body/normal k$dgg
        " Хитрое выражение с регуляркой
        " Оно обрабатывает содержимое открывающего тега body, извлекает
        " значения параметров bgcolor и text, и заменяет этот тег body
        " на открывающий тег font, в котором в качестве цвета указывается
        " параметр, который находился в параметре text тега body
        %s/<body\s*\(bgcolor="\#[a-f0-9]\{6\}"\)\s*text=\("\#[a-f0-9]\{6\}"\)\s*>/<font color=\2>/i
        " Заменяет всё, что находится между закрывающим тегом body
        " и закрывающим тегом html, на закрывающий тег font
        %s#</body>\(.\|\n\)*</html>#</font>#i
        " Удаляет все теги br
        %s#<br>##i
        " Удаляет лишний перенос строки после самой первой строки
        normal ggJ
        " Удаляет лишний перенос строки перед самой последней строкой
        normal GkJ
        " Компируем в буфер всё содержимое TODO: копировать в именованный
        " буфер
        normal ggVGy
        " Выходим из окна, не сохраняя ничего
        q!
        " Вставляем вместо выделенного фрагмента получившийся код
        normal gvp
endf


(Подсветка этого кода сгенерирована им самим же.)

Добавляем возможность вызова команды для выделенного промежутка строк:
command -range=% Code :call Code(<line1>,<line2>)

Наконец, вешаем всё это на клавишу F4:
vmap <F4> :Code<CR>

Как этим пользоваться: выделяем фрагмент кода, подсветку которого хотим сделать, жмём F4, и вуаля! Вместо фрагмента кода появляется html-код с подсветкой.



Чтобы проще было разобраться как работают команды внутри функции Code, опишу как можно выполнить эту функцию вручную и пошагово. Пусть у нас есть код, подсветку которого хочется сделать:
:a CreateWindowExA DWORD LPCTSTR LPCTSTR DWORD LONG LONG
                   LONG LONG HWND HMENU HINST LPVOID    HWND user32;
:a DefWindowProcA HWND UINT WPARAM LPARAM               LRESULT user32;
:a DestroyWindow HWND                                   BOOL user32;
:a DispatchMessageA LPMSG                               LONG user32;


Выделяем его при помощи shift+v (в терминах вима S-V), выполняем
:'<,'>TOhtml

У нас открывается новое окно со следующим содержимым:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>D:\proj\DForth\trunk\release\units\windows.de.html</title>
<meta name="Generator" content="Vim/7.3">
<meta http-equiv="content-type" content="text/html; charset=windows-1251">
</head>
<body bgcolor="#000000" text="#a8a8a8"><font face="monospace">
<font color="#8700d7">:a CreateWindowExA</font>&nbsp;DWORD LPCTSTR LPCTSTR DWORD LONG LONG <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LONG LONG HWND HMENU HINST LPVOID&nbsp;&nbsp;&nbsp;&nbsp;HWND <font color="#8700d7">user32;</font><br>
<font color="#8700d7">:a DefWindowProcA</font>&nbsp;HWND UINT WPARAM LPARAM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LRESULT <font color="#8700d7">user32;</font><br>
<font color="#8700d7">:a DestroyWindow</font>&nbsp;HWND&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BOOL <font color="#8700d7">user32;</font><br>
<font color="#8700d7">:a DispatchMessageA</font>&nbsp;LPMSG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LONG <font color="#8700d7">user32;</font><br></font>
</body>
</html>


Выполняем
:%g/<body/normal k$dgg
, удаляется всё, что выше body:
<body bgcolor="#000000" text="#a8a8a8"><font face="monospace">
<font color="#8700d7">:a CreateWindowExA</font>&nbsp;DWORD LPCTSTR LPCTSTR DWORD LONG LONG <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LONG LONG HWND HMENU HINST LPVOID&nbsp;&nbsp;&nbsp;&nbsp;HWND <font color="#8700d7">user32;</font><br>
<font color="#8700d7">:a DefWindowProcA</font>&nbsp;HWND UINT WPARAM LPARAM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LRESULT <font color="#8700d7">user32;</font><br>
<font color="#8700d7">:a DestroyWindow</font>&nbsp;HWND&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BOOL <font color="#8700d7">user32;</font><br>
<font color="#8700d7">:a DispatchMessageA</font>&nbsp;LPMSG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LONG <font color="#8700d7">user32;</font><br></font>
</body>
</html>


Теперь выполним сперва
:%s/<body\s*\(bgcolor="\#[a-f0-9]\{6\}"\)\s*text=\("\#[a-f0-9]\{6\}"\)\s*>/<font color=\2>/i
затем
:%s#</body>\(.\|\n\)*</html>#</font>#i
Первая команда затронет строку, в которой открывается body, вторая -- строки, в которой закрываются body и html:
<font color="#a8a8a8"><font face="monospace">
<font color="#8700d7">:a CreateWindowExA</font>&nbsp;DWORD LPCTSTR LPCTSTR DWORD LONG LONG <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LONG LONG HWND HMENU HINST LPVOID&nbsp;&nbsp;&nbsp;&nbsp;HWND <font color="#8700d7">user32;</font><br>
<font color="#8700d7">:a DefWindowProcA</font>&nbsp;HWND UINT WPARAM LPARAM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LRESULT <font color="#8700d7">user32;</font><br>
<font color="#8700d7">:a DestroyWindow</font>&nbsp;HWND&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BOOL <font color="#8700d7">user32;</font><br>
<font color="#8700d7">:a DispatchMessageA</font>&nbsp;LPMSG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LONG <font color="#8700d7">user32;</font><br></font>
</font>


Удаляем все теги br:
:%s#<br>##i

Получаем:
<font color="#a8a8a8"><font face="monospace">
<font color="#8700d7">:a CreateWindowExA</font>&nbsp;DWORD LPCTSTR LPCTSTR DWORD LONG LONG
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LONG LONG HWND HMENU HINST LPVOID&nbsp;&nbsp;&nbsp;&nbsp;HWND <font color="#8700d7">user32;</font>
<font color="#8700d7">:a DefWindowProcA</font>&nbsp;HWND UINT WPARAM LPARAM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LRESULT <font color="#8700d7">user32;</font>
<font color="#8700d7">:a DestroyWindow</font>&nbsp;HWND&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BOOL <font color="#8700d7">user32;</font>
<font color="#8700d7">:a DispatchMessageA</font>&nbsp;LPMSG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LONG <font color="#8700d7">user32;</font></font>
</font>


Наконец, удаляем первый перенос строки и последний:
ggJ
GkJ
Получаем:
<font color="#a8a8a8"><font face="monospace"> <font color="#8700d7">:a CreateWindowExA</font>&nbsp;DWORD LPCTSTR LPCTSTR DWORD LONG LONG
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LONG LONG HWND HMENU HINST LPVOID&nbsp;&nbsp;&nbsp;&nbsp;HWND <font color="#8700d7">user32;</font>
<font color="#8700d7">:a DefWindowProcA</font>&nbsp;HWND UINT WPARAM LPARAM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LRESULT <font color="#8700d7">user32;</font>
<font color="#8700d7">:a DestroyWindow</font>&nbsp;HWND&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BOOL <font color="#8700d7">user32;</font>
<font color="#8700d7">:a DispatchMessageA</font>&nbsp;LPMSG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LONG <font color="#8700d7">user32;</font></font> </font>


Всё, код полностью готов для вставки в блог.


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

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

Постоянные читатели

Обо мне

Моя фотография
Мой e-mail: vitek_03(at)mail(dot)ru