суббота, 17 ноября 2012 г.

Статистика, diff, подсветка

Здесь я уже рассказывал, как с помощью утилиты diffstat можно выводить статистические данные по коммитам в Subversion, систематизированные по отдельным пользователям. На этот раз я хочу расширить возможности данного подхода путем абстрагирования параметров систематизации и улучшения пользовательского интерфейса. Вторая задача, в частности, означает, что команда-однострочник будет заменена программой с возможностью задания различных опций. Программа представляет собой bash-скрипт и выглядит так:
#!/bin/bash - 

PrintUsage()
{
    echo "Usage: `basename $0` [-m] [-l level] [-p pattern] [-w width] [path]"
    echo "  -m          calulate modifications, insertions and deletions"
    echo "  -l level    history level of svn log command"
    echo "  -p pattern  filter commits according pattern"
    echo "  -w width    width of diffstat histogram"
    echo "  path        in specified file or directory only"
}

while [ $1 ]
do
    case $1 in
        -h|-help|--help)    PrintUsage ; exit 0 ;;
        -m)                 modifications=-m ;;
        -l)                 shift ; level="-l $1" ;;
        -p)                 shift ; pattern=$1 ;;
        -w)                 shift ; width="-w $1" ;;
        *)                  path=$path' '$1 ;;
    esac
    shift
done

for revision in \
    `svn log $level $path | grep '^r[0-9]\+.*'$pattern | awk '{print $1}' |\
     sed 's/r//g'`
do
    svn diff -c$revision $path
done | diffstat -v $modifications -f 4 $width
Львиную долю кода составляет функция PrintUsage() и разбор опций командной строки. Основной код размещен внутри цикла for и представляет собой ту же самую, слегка видоизмененную, однострочную команду. Кстати, PrintUsage() дает полное представления об опциях программы и я не буду на них останавливаться. Я поместил этот код внутрь исполняемого файла svndiffstat в директории $HOME/bin/.

Теперь мы сделаем так, чтобы вывод скрипта был подсвечен. Я показывал, как этого можно добиться с помощью программы hl здесь и здесь. Следуя данной схеме, определим сниппет dstat в $HOME/.hlrc:
snippet dstat   -196 '\++[!-]*$' '(?<=\|)\s*\d+\s*\d+' '\d+ (?=insertion)' \
                '(?<=\()\+(?=\))' \
                -33 '\-+!*$' '(?<=\|)\s*\d+\s*\d+\s*\d+' '\d+ (?=deletion)' \
                '(?<=\()-(?=\))' \
                -30 '!+$' '(?<=\|)\s*\d+\s*\d+\s*\d+\s*\d+' \
                '\d+ (?=modification)' '(?<=\()!(?=\))' \
                -101 '(?<=\|)\s*\d+' -82 '\s+\|\s+' -155 '/' -215 '[^/]+\s+\|' \
                -203 '^\s*[^/]+/' -155 '\d+ (?=file)'
и новую функцию svndiffstat в $HOME/.hl_functions:
function svndiffstat
{
    `env which svndiffstat` $@ | hl -sdstat
}
Результат работы svndiffstat представлен на картинке:


Здесь была запрошена статистика по коммитам за февраль 2011 года. Фактически значение опции -p задает регулярное выражение для поиска внутри строки, выводимой командой svn log и начинающейся с номера ревизии, такая строка включает имя пользователя, дату коммита и число измененных строк: это и есть параметры, по которым можно осуществлять выборку. Представленная статистика была собрана в соответствии с метаданными svn, находящимися внутри текущей директории, кроме того, svndiffstat позволяет изменить директорию для сбора статистики, если таковая будет задана в конце списка аргументов командной строки.

Кстати говоря, поскольку программа hl не включает подсветку при выводе в пайп, то можно изменять правила подсветки вывода svndiffstat, например добавить подсветку слова Energy в примере на картинке:
$ svndiffstat -p 2011-02 -w 60 -m | hl -sdstat -98 Energy
Раз уж речь зашла о diff и подсветке вывода программ, то хотелось бы привести соответствующие настройки .hlrc и .hl_functions. (Кстати, раньше для подсветки diff я использовал программу colordiff. Однако colordiff имела существенный недостаток: невозможность использования всех цветов на 256-цветных терминалах.)

Итак, в .hlrc следует добавить
snippet diff    -155 -b '^Index:\s+.*' '^=+$' '^diff.*' '^Binary.*' \
                -180 '^Только.*' '^\\.*' -76 '^@.*' '^\d.*' -rb -196 '^[+>].*' \
                -26 '^[-<].*'
a в .hl_functions
function diff
{
    `env which diff` $@ | hl -sdiff
}

function svndiff
{
    svn diff $@ | hl -sdiff
}
Теперь вывод diff будет всегда подсвечиваться на экране терминала. Кроме того, здесь определена еще одна функция svndiff для подсветки, как не трудно догадаться, вывода команды svn diff. Кстати, наверняка нам понадобятся аналогичные определения cvsdiff, gitdiff, hgdiff и т.п. Чтобы не плодить множество подобных функций, можно воспользоваться командой оболочки eval внутри цикла for по всем типам VCS, которая определит все функции за нас:
for vcs in cvs svn hg git ; do
    eval "function ${vcs}diff
    {
        $vcs diff \$@ | hl -sdiff
    }"
done
В дополнение к сказанному, хочу затронуть тему вывода на экран терминала подсвеченного программного кода. Универсальные подсветчики типа hl или grc здесь не очень подходят, так как писать сложные правила подсветки для множества языков программирования с использованием одних только регулярных выражений - задача нереальная. Поэтому для этой цели я использую программу GNU source-highlight, обернув ее, как обычно, в новую функцию оболочки. Функцию я назвал cathl и поместил ее в $HOME/.bashrc.
function cathl
{
    source-highlight -f esc -q -i $@
}
Функция cathl выводит на экран терминала содержимое своего аргумента - исходного файла. Если нужно вывести подсвеченный код в другой файл, то следует добавить в список аргументов после (здесь это важно) имени исходного файла опцию -o output-file. Кроме этого в cathl в принципе доступны другие опции source-highlight, например указание языка исходного текста там где это нужно. Однако изменить формат вывода (опция -f) в cathl не получится, так как он уже закреплен за цветовыми escape последовательностями терминала (-f esc).

Главным недостатком source-highlight лично для меня является недоступность всей 256-цветовой палитры для подсветки. Однако в последней версии 3.1.7 этот недостаток отсутствует. У меня в Fedora 17 стоит более старая версия 3.1.4, ну а если вам повезло, или вы сами решите собрать source-highlight из исходников, то можете смело заменять -f esc в cathl на -f esc256.

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

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