Показаны сообщения с ярлыком TOhtml. Показать все сообщения
Показаны сообщения с ярлыком TOhtml. Показать все сообщения

четверг, 9 января 2014 г.

vim: плагин publish_helper

Работу, начатую здесь и здесь, решил оформить в виде плагина vim (страница на гитхабе и страница на www.vim.org). Полная документация доступна по ссылкам, а также внутри плагина. Плагин состоит из двух частей. Первая часть - это собственно скрипт на viml, в котором определены команды MakeHtmlCodeHighlight (переименованная и улучшенная MakeBlogArticle) и MakeTexCodeHighlight (тоже улучшенная по сравнению с первой реализацией). Вторая часть написана на haskell и представляет собой фильтр для pandoc (фильтры доступны в pandoc начиная с версии 1.12), который позволяет подменять исходные блоки кода (CodeBlock) внутри абстрактного синтаксического дерева, представляющего документ, на неформатированные блоки (RawBlock), содержащие подсвеченный с помощью vim код.

Для того, чтобы показать как это работает, возьмем оригинальный пример из руководства пользователя pandoc, в котором приведена классическая реализация быстрой сортировки на haskell, и добавим туда еще пару образцов кода.
### Original example from [*Pandoc User's Guide*](http://johnmacfarlane.net/pandoc/README.html#fenced-code-blocks)

~~~~ {#mycode .haskell .numberLines hl="vim" startFrom="100"}
qsort []     = []
qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++
               qsort (filter (>= x) xs)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

### Small C++ code sample

~~~~ {.cpp hl="vim"}
G4UIQt *  qtSession( dynamic_cast< G4UIQt * >( session ) );

if ( qtSession )
{
    qtSession->AddMenu( histoMenuHandle, histoMenuLabel );
    BuildMenuTree( qtSession, histoMenuHandle, gDirectory->GetList() );
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

### Content of my *~/.vimrc.pandoc*

~~~~ {#vimrc_pandoc .vim .numberLines hl="vim"}
syntax on

filetype on
filetype indent on
filetype plugin on
filetype plugin indent on

let g:lucius_style = 'light'
let g:lucius_contrast = 'high'
let g:lucius_contrast_bg = 'high'

set nocp    " for line breaks with backslashes
colorscheme lucius

let g:PhCtrlTrans = 0
let g:PhHtmlPreAttrs = 'style="white-space: pre-wrap;"'

runtime plugin/publish_helper.vim
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Это синтаксическая подсветка цветовой схемы lucius для типа файла pandoc, который будет доступен, если вы установите плагин для pandoc отсюда. Я вставил ее сюда из vim дословно с помощью команды MakeHtmlCodeHighlight.

Идем дальше. Сохраняем этот пример в файле example.md и генерируем HTML файл example.html с помощью pandoc и фильтра vimhl из нашего плагина.
pandoc --standalone -t html -F vimhl -o example.html example.md
Получаем файл example.html с таким содержимым:
 

Original example from Pandoc User's Guide

100  qsort []     = []
101  qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++
102                 qsort (filter (>= x) xs)

Small C++ code sample

G4UIQt *  qtSession( dynamic_cast< G4UIQt * >( session ) );

if ( qtSession )
{
    qtSession->AddMenu( histoMenuHandle, histoMenuLabel );
    BuildMenuTree( qtSession, histoMenuHandle, gDirectory->GetList() );
}

Content of my ~/.vimrc.pandoc

 1  syntax on
 2  
 3  filetype on
 4  filetype indent on
 5  filetype plugin on
 6  filetype plugin indent on
 7  
 8  let g:lucius_style = 'light'
 9  let g:lucius_contrast = 'high'
10  let g:lucius_contrast_bg = 'high'
11  
12  set nocp    " for line breaks with backslashes
13  colorscheme lucius
14  
15  let g:PhCtrlTrans = 0
16  let g:PhHtmlPreAttrs = 'style="white-space: pre-wrap;"'
17  
18  runtime plugin/publish_helper.vim

Это цвета схемы lucius с правильной подсветкой синтаксиса всех образцов. А теперь создадим аналогичный PDF документ.
pandoc --standalone -t latex -F vimhl -o example.tex example.md
Открываем файл example.tex и вставляем в преамбулу строки
\usepackage{color}
\usepackage{xcolor}
\usepackage{fancyvrb}
\newcommand{\VerbBar}{|}
\newcommand{\VERB}{\Verb[commandchars=\\\{\}]}
\DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}}
\usepackage{framed}
\newenvironment{Shaded}{
  \definecolor{shadecolor}{rgb}{1.0, 1.0, 0.9}
  \setlength\parskip{0cm}
  \setlength\partopsep{-\topsep}
  \addtolength\partopsep{0.2cm}
  \begin{shaded}
    \scriptsize
}{\end{shaded}}
Зачем это нужно, вы можете прочесть в документации к плагину. Завершаем генерацию example.pdf.
latexmk -pdf example
Вот скриншот получившегося документа:

суббота, 25 августа 2012 г.

Как я вставляю подсвеченный код в блог

С помощью vim. Хотя раньше для этой цели я пользовался неплохой программой source-highlight, с vim, при должной настройке, это сделать еще проще. В vim есть плагин TOhtml (он обычно сразу доступен в системном дистрибутиве) - это основа подхода, о котором я буду говорить. Еще недавно я использовал его в чистом виде, с необходимостью ручной обработки полученного HTML кода, однако теперь у меня есть волшебный скрипт, который делает всю грязную работу и подготавливает код к простой вставке в блог в режиме верстки HTML. Этот скрипт нужно добавить в файл .vimrc, его текст я привожу ниже с комментариями по строкам.

Сразу хочу отметить, что для работы в vim я использую темную цветовую схему с прозрачным фоном на основе схемы xterm16. Эта схема не годится для текста с белым фоном, который я использую в блоге. Поэтому для создания HTML кода я временно переключаюсь на светлую цветовую схему. Для этого я выбрал схему lucius (которая недавно обновилась до версии 8.1) с соответствующими настройками, которые также показаны в следующем коде.
229 " ---- lucius colorscheme settings and command MakeBlogArticle
230 " ----
231 let g:lucius_style = 'light'
232 let g:lucius_contrast = 'high'
233 let g:lucius_contrast_bg = 'high'
234 
235 fun<SID>make_blog_article(prepare_for_insertion, line1, line2)
236     let colors = g:colors_name
237     colorscheme lucius
238     let g:html_use_css = 0
239     exe a:line1.",".a:line2."TOhtml"
240     unlet g:html_use_css
241     exe "colorscheme ".colors
242     setlocal nowrap
243     if a:prepare_for_insertion
244         1;/^<font face=/-1d
245         1s/.*/<pre><tt>/
246         silent $;?^</font?+1d
247         $s/.*/<\/tt><\/pre>/
248         %s/<br>$//
249         if getline(2) =~ '^[[:blank:]]*$'
250             2;/[^[:blank:]]\+/-1d
251         endif
252         if getline(line('$') - 1) =~ '^[[:blank:]]*$'
253             silent $-1;?[^[:blank:]]\+?+1d
254         endif
255         normal ggJx0
256     endif
257 endfun
258 
259 command -range=% MakeBlogArticle
260             \ silent call <SID>make_blog_article(1<line1><line2>)
В строках 231-233 находятся настройки цветовой схемы lucius. В строках 259-260 определена команда MakeBlogArticle, которая выполняет всю работу с помощью вызова функции make_blog_article(). Команда MakeBlogArticle может выполнять подсветку как для всего кода в буфере, так и внутри отдельной выделенной области. Для этого в функцию make_blog_article() передаются два аргумента line1 и line2, которые соответствуют номерам строк, ограничивающих выделенную область. Еще один аргумент prepare_for_insertion указывает на то, что код, сгенерированный командой TOhtml нужно будет преобразовать для вставки в блог (заменить HTML хедер и футер на теги <pre><tt> и </tt></pre> соотвественно, удалить теги <br> и т.п.).

В строках 235-257 находится тело функции make_blog_article(). Разберемся, что же в ней происходит. Строки 236-237: запоминаем текущую цветовую схему и переключаемся на новую. Строки 239-241: выполняем команду TOhtml в переданном диапазоне, определяемом аргументами line1 и line2. По умолчанию в TOhtml используется CSS, для вставки в блог это не годится, поэтому мы определяем равной нулю специальную переменную g:html_use_css перед самым вызовом TOhtml, а затем удаляем ее. В строке 241 переключаемся на исходную цветовую схему. После вызова TOhtml  курсор находится в новом буфере с HTML кодом. В строке 242 указываем, что vim не следует переносить длинные строки при достижении границы видимой области (это дело вкуса, но в данном случае мне удобнее, когда длинные строки не переносятся).

В строках 243-256 происходит подготовка сгенерированного HTML кода для вставки в блог. В строке 244 переходим на первую строку в буфере и удаляем все строки вплоть до  первого вхождения ^<font face= (после него начинается полезный код). В строке 245 заменяем первую строку (которой теперь оказалась строка с первым вхождением ^<font face=) на <pre><tt>. Таким образом, мы заменили HTML хедер на <pre><tt>. В строках 246-247 производится аналогичная замена HTML футера на </tt></pre>. В строке 248 удаляем все переносы строк <br>: при использовании тега <pre> они не нужны. Далее идут в принципе необязательные изменения, настраивающие отступы впереди и в конце сгенерированного HTML кода. В строках 249-254 удаляем все пустые строки в буфере после первой строки и перед последней строкой. В строке 255 переводим курсор на первую строку буфера и соединяем ее со второй строкой.

Теперь остается выделить все строки в буфере и вставить их в редактируемое поле в блоге в режиме верстки HTML.

Кстати я не уверен, что замена HTML хедера и футера на <pre><tt> и </tt></pre> является оптимальным решением, но в моем случае она работает.