31 окт. 2010 г.

Литературное программирование в Vim

Недавно, я наткнулся на описание и действующий пример концепции программирования, которая называется литературным или грамотным программированием (literate programming).
Согласно этой концепции программист больше не вынужден мучительно писать код и комментарии к нему. Достаточно написать подробную статью о своей программе, наподобие той, что на IBM developerWorks. После, при помощи специальной утилиты можно получить как готовый файл со статьей, так и исходный код.
Подробнее об этой концепции можно почитать в Википедии, в блоге моего хорошего знакомого (там же лежит и рабочий пример счетчика на VHDL, написанного с применением этой концепции) и в ЖЖ anton_nazarov'а.
Для написания статьи об исходном коде мной естественно использовался Vim. К сожалению, в нем не так уж и много функциональных плагинов для работы с используемой мной системой литературного программирования NOWEB.
Я нашел и использовал один плагин, который был создан специально для работы с NOWEB - noweb.vim. Данный плагин умеет немногое - лишь подсвечивать части файла с документацией латеховской или html-ной подсветкой и подсвечивать части файла с исходным кодом, указанной в конфигурации подсветкой (как sql, как c и т.д.). К сожалению, в плагине отсутствует возможность автоматического распознавания типа исходного кода в документе и включения соответствующей подсветки. Еще плагин умеет сворачивать блоки с кодом.
Сворачивание блоков с кодом
В плагине обнаружилась одна неприятная особенность - если открыть какой-нибудь документ в той же копии Vim'а, что и статью о коде, то подсветки у этого документа не будет. Я не хотел долго искать причину такого поведения плагина и просто закомментировал строку #29 в файле noweb.vim:
"execute "syntax include @Code syntax/" . noweb_language . ".vim"
Настройки плагина просты и занимают буквально несколько строк:
"настройки для noWEB
au BufRead,BufNewFile *.nw setlocal filetype=noweb
"Разметка документа
let noweb_backend="tex"
"Сворачиваем блоки кода
let noweb_fold_code=1
Также, я добавил несколько биндингов, удобных как для LaTeX'а, так и для NOWEB:
au BufRead,BufNewFile *.tex,*.nw inoremap %- %---------------------------------------------------------------------------<CR>
au BufRead,BufNewFile *.tex,*.nw inoremap %= %===========================================================================<CR>
au BufRead,BufNewFile *.tex,*.nw inoremap { {}<Left>
au BufRead,BufNewFile *.tex,*.nw inoremap \bei \begin{itemize}<CR>
au BufRead,BufNewFile *.tex,*.nw inoremap \ei \end{itemize}<CR>
au BufRead,BufNewFile *.tex,*.nw inoremap \bee \begin{enumerate}<CR>
au BufRead,BufNewFile *.tex,*.nw inoremap \ee \end{enumerate}<CR>
au BufRead,BufNewFile *.tex,*.nw inoremap \it \item
В моем vim'е есть меню для создания различных новых проектов в текущем каталоге - после выбора типа нового проекта происходит копирование соответствующих файлов в текущий каталог и их открытие. В это же меню был добавлен и NOWEB:
" Create new project 
menu NewProj.C++ :!cp -r ~/.vim/mproj/c++/* .<CR>:e ./src/main.cpp<CR>
menu NewProj.C :!cp -r ~/.vim/mproj/c/* .<CR>:e ./main.c<CR>
menu NewProj.LaTeX :!cp -r ~/.vim/mproj/latex/* .<CR>:e ./report.tex<CR>
menu NewProj.NoWeb :!cp -r ~/.vim/mproj/noweb/* .<CR>:e ./article.nw<CR>
map <C-c>np :emenu NewProj.<TAB>
Меню создания нового проекта
В каталоге ~/.vim/mproj/noweb/ содержатся всего два файла - article.nw - файл со статьей о коде и Makefile. Вот их содержимое:
\documentclass[draft, a4paper, 12pt]{article}
\usepackage[T2A]{fontenc}
\usepackage{ucs}
\usepackage[utf8x]{inputenc}
\usepackage[english, russian]{babel}
\usepackage{listings}
\usepackage{hyperref}
\usepackage{noweb}
\pagestyle{plain}

\begin{document}

%---------------------------------------------------------------------------

\begin{titlepage} % начало титульника
\begin{center}

\large Санкт-Петербургский государственный университет информационных технологий
механики и оптики\\[4.5cm]

\huge Лабораторная работа \No 1\\[0.6cm]
\large по теме @<<блаблабла@>>\\[3.7cm]

\begin{minipage}{0.5\textwidth}
\begin{flushleft}
\emph{Автор:} Андриенко~Евгений\\
\emph{Группа:} 4103\\
\emph{Факультет:} КТиУ\\
\emph{Преподаватель:} Блаблабла\\
\end{flushleft}
\end{minipage}

\vfill

Санкт-Петербург\\
{\large \today}

{\large \LaTeX}

\end{center}
\thispagestyle{empty} % не нумеруем страницу
\end{titlepage} % конец титульника

%---------------------------------------------------------------------------

\tableofcontents

\end{document}

all: tex

tex: article.nw
    noweave -delay article.nw > report.tex
    # for normal contents generation
    pdflatex report.tex
    pdflatex report.tex

.PHONY: clean
clean:
    rm -f report.*
Мною были написаны пара лабораторных работ на ассемблере и на языке PL/SQL с применением принципов литературного программирования. Лучше всего, на мой взгляд удалась лабораторная с PL/SQL - мне больше не требовалось сидеть и думать как написать то или иное действие для получения результата. Я мог разбить всю программу на отдельные структурированные куски и обстоятельно описать каждый из них, не отвлекаясь на несущественные в данный момент вещи.
После сборки статьи в исходный код мне потребовалось лишь подправить пару синтаксических ошибок и процедура заработала.
Посмотреть на эту лабораторную можно здесь: http://goo.gl/BNMQ.

Буду рад, если кто-нибудь расскажет в комментариях о более функциональных плагинах к NOWEB для Vim'а, наподобие emacs'ового noweb.el.