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

воскресенье, 31 января 2016 г.

vim-xkbswitch: управление keymap в нормальном режиме и в строках поиска

На днях добавил указанную фичу в vim-xkbswitch. Суть проста. При выходе из режима ввода (Insert mode) в нормальный режим (Normal mode) хотелось бы, чтобы после ввода команд r и f, а также в режиме поиска в командной строке (команды / и ?), системная раскладка переключалась на ту, что была в режиме ввода. К сожалению, реализовать такое с нуля технически весьма затруднительно. К счастью, можно воспользоваться встроенной в vim поддержкой keymap, и более того, управлять ею с помощью настройки iminsert и imsearch при выходе в нормальный режим. В общем, если есть желание управлять keymap из vim-xkbswitch, то в файл .vimrc следует добавить такие строки.
let g:XkbSwitchAssistNKeymap = 1    " for commands r and f
let g:XkbSwitchAssistSKeymap = 1    " for search lines
set keymap=russian-jcukenwin
set iminsert=0
set imsearch=0
Значение keymap в данном случае зависит от дополнительной раскладки, с которой вы работаете. Если по какой-то причине имя системной раскладки (возвращается бэкенд-библиотекой, например xkb-switch) не совпадает с именем keymap (которое обычно присваивается переменной b:keymap_name в файле keymap), то можно настроить отображение из первого во второе, например
let g:XkbSwitchKeymapNames = {'ru' : 'ru_keymap'}
Здесь ru — имя системной раскладки, а ru_keymap — предполагаемое значение b:keymap_name. Если вы работаете с несколькими раскладками одновременно (например, стандартной для нормального режима американской, русской и украинской), то возможно при выходе из режима ввода вы захотите, чтобы keymap указывал на ту из трех раскладок, которая была использована последней. Для этого вам понадобится динамическая настройка keymap, которую можно задействовать с помощью следующих настроек в .vimrc (вместо тех, что были приведены выше).
let g:XkbSwitchAssistNKeymap = 1    " for commands r and f
let g:XkbSwitchAssistSKeymap = 1    " for search lines
let g:XkbSwitchDynamicKeymap = 1
let g:XkbSwitchKeymapNames = {'ru' : 'russian-jcukenwin',
            \ 'uk' : 'ukrainian-jcuken'}
Обратите внимание, здесь не требуется настройка keymap по умолчанию (хотя и не возбраняется), а в качестве значений в словаре g:XkbSwitchKeymapNames используются имена keymap, а не значения b:keymap_name. Если в нормальном режиме вы захотите переключиться на стандартную раскладку нормального режима, то просто временно зайдите в режим ввода и в нем переключитесь на соответствующую раскладку (это можно также сделать командой :setlocal iminsert=0). В строке поиска то же самое можно сделать сочетанием клавиш Ctrl-^. Все это хорошо, но есть одна серьезная проблема. Системный индикатор раскладки будет по-прежнему показывать стандартную в нормальном режиме раскладку, ведь vim-xkbswitch здесь не действует, а keymap не влияет на системную раскладку. На помощь приходит статусная строка, которую можно легко настроить для отображения значения keymap, когда iminsert равен 1, в плагине Powerline. Индикатор keymap будет отображать активную keymap раскладку для команд r и f и строк поиска, в случае, если iminsert равен 1, в то время как индикатор системной раскладки будет отображать стандартную для нормального режима раскладку. В режиме ввода индикатор keymap не действует, поскольку vim-xkbswitch отключает keymap установкой iminsert в 0. Такое решение, кстати, позволяет пользователю видеть, какая раскладка станет активной при переходе из нормального режима в режим ввода, а это здо́рово, на мой взгляд! Я покажу, как настроить индикатор keymap в старом Powerline, в новейших репликах типа vim-airline действия должны быть похожи. Итак, в файле autoload/Powerline/Segments.vim в массиве, передаваемом в функцию Pl#Segment#Init() перед строкой, содержащей слово fileformat, вставляем строки
    \ Pl#Segment#Create('keymap_name'     ,
        \'%{&iminsert && exists("b:keymap_name") ? b:keymap_name : ""}',
        \ Pl#Segment#Modes('!N')),
, в файле autoload/Powerline/Themes/default.vim (или в другом файле темы Powerline, в зависимости от того, какую тему вы используете) в список, передаваемый в функцию Pl#Theme#Buffer(), перед строкой, содержащей слово fileformat, вставляем строку
        \ , 'keymap_name'
, и, наконец, в файле autoload/Powerline/Colorschemes/default.vim (или в другом файле цветовой схемы Powerline, если вы используете нестандартную схему), в произвольном месте списка, передаваемого в функцию Pl#Colorscheme#Init(), вставляем строки
    \ Pl#Hi#Segments(['keymap_name'], {
        \ 'n': ['brightestorange', 'gray2'],
        \ 'i': ['brightestorange', 'darkestblue'],
        \ }),
    \
После этого выполняем команду
:PowerlineClearCache
, перезагружаем vim и наслаждаемся индикацией keymap. Напоминаю, что стандартная в нормальном режиме раскладка отображаться не будет. Вот так может выглядеть статусная строка Powerline с индикатором keymap (обратите внимание на оранжевые буквы ru).

вторник, 20 августа 2013 г.

vim: редактирование файлов от имени суперпользователя, добавление новых сегментов Powerline

Настроить редактирование системных файлов от имени суперпользователя на домашнем компьютере несложно. Заводим файл в директории /etc/sudoers.d/ с произвольным именем, например users. Помещаем в него строки
Host_Alias    LOCAL = desktop
Cmnd_Alias    VIM = /usr/bin/vim, /usr/bin/vimdiff
Defaults!VIM  env_keep += "HOME"
username      LOCAL = NOPASSWD: VIM
Здесь имя desktop соответствует имени локального хоста. Если вы специально не изменяли это имя в вашей системе, то вместо desktop напишите localhost. Алиас хоста LOCAL используется в последней строке и разрешает редактирование файлов от имени суперпользователя только с локального компьютера. Имя username соответствует имени учетной записи пользователя, которому будет позволено редактировать файлы с помощью sudo. В данном примере мы разрешили пользователю username запускать программы vim и vimdiff от имени суперпользователя без ввода пароля. Кроме того, в третьей строке мы попросили sudo использовать оригинальное значение переменной окружения $HOME: это нужно для того, чтобы vim загружал скрипт .vimrc и все дополнительные плагины из домашней директории пользователя username, а не из директории суперпользователя.

Что здесь нехорошо? Собственно то, что мы дали пользователю username возможность выполнить любую системную команду с привилегией суперпользователя! Не забываем, что из vim можно выполнить системную команду с помощью :!. Именно поэтому в первом предложении я написал на домашнем компьютере: не стоит давать такие привилегии обычному пользователю username на промышленном сервере.

Последнее украшательство - добавление алиасов в файл .bashrc:
alias svim='sudo vim'
alias svimdiff='sudo vimdiff'
Теперь vim с правам суперпользователя можно вызывать как svim, а vimdiff - как svimdiff.

Всё это прекрасно, но хотелось бы, чтобы vim каким-нибудь образом отмечал то, что мы редактируем файл от имени суперпользователя. Что ж, это достаточно легко сдедать с помощью плагина Powerline. Лично я по-прежнему использую старую версию плагина, которую можно загрузить отсюда, поэтому следующий рецепт относится именно к ней.

Итак, наша задача - добавить новый сегмент, на котором, в случае, если пользователь редактирует файл от имени суперпользователя, во всех режимах vim будет красоваться жирная, хорошо заметная надпись SUDO на красном фоне. Поскольку это сообщение достаточно важное, пусть оно будет находиться в начале статусной строки. Для этого в файле .vim/autoload/Powerline/Segments.vim перед строкой
    \ Pl#Segment#Create('paste_indicator' , '%{&paste ? "PASTE" : ""}', Pl#Segment#Modes('!N')),
добавим похожую строку
    \ Pl#Segment#Create('sudo_indicator'  , '%{empty($SUDO_USER) ? "" : "SUDO"}', Pl#Segment#Modes('!N')),
Это и есть новый сегмент, который мы назвали sudo_indicator (первый аргумент функции Pl#Segment#Create()). Второй аргумент Pl#Segment#Create() соответствует коду, который будет выполнен для определения текста сегмента. В нашем случае мы опираемся на тот простой факт, что команда sudo определяет переменную окружения $SUDO_USER, в которой записано имя пользователя, получившего привилегии суперпользователя, соответственно, если эта переменная определена (то есть vim был запущен из sudo), то второй аргумент будет равен SUDO, иначе - пустой строке. Третий параметр: Pl#Segment#Modes('!N') - говорит о том, что если текущее окно не в фокусе, то данный сегмент не будет отображаться - это нам вполне подходит.

Далее помещаем новый сегмент на первую позицию списка всех сегментов. Для этого в файле .vim/autoload/Powerline/Themes/default.vim добавляем строку
        \ , 'sudo_indicator'
перед строкой
        \ , 'paste_indicator'
а в файле .vim/autoload/Powerline/Colorschemes/default.vim описываем цветовые характеристики сегмента:
    \
    \ Pl#Hi#Segments(['sudo_indicator'], {
        \ 'n': ['brightgreen''brightestred', ['bold']],
        \ }),
(это можно поместить, например, за определением
    \ Pl#Hi#Segments(['SPLIT'], {
        \ 'n': ['white''gray2'],
        \ 'N': ['white''gray0'],
        \ 'i': ['white''darkestblue'],
        \ }),
). Если вы используете другую тему или цветовую схему Powerline (то есть не default), то данные определения нужно поместить в соответствующие файлы. Итак, почти все готово, обновляем кэш Powerline:
:PowerlineClearCache
и открываем какой-нибудь файл с помощью svim. Вот какую статусную строку я увидел после этих изменений:


Хорошо, но не очень. Видите темно-красные артефакты вокруг стрелки с SUDO? Исследование показало, что они связаны с сегментом paste_indicator, когда его текст соответствует пустой строке. Вы можете убедиться в этом выполнив
:set paste
и
:set nopaste
несколько раз. К сожалению, как я понял, данная версия Powerline не способна удовлетворительно решить проблему с сегментом, который может содержать пустое значение. Если такой сегмент находится не в самом начале списка сегментов, то мы будем время от времени получать подобные стрелочные артефакты. В нашем случае возможны четыре решения данной проблемы:
  1. удалить сегмент paste_indicator (плохо);
  2. сделать так, чтобы надпись в paste_indicator присутствовала всегда (т.е. PASTE или NOPASTE - тоже не очень хорошо - зачем нам избыточная информация);
  3. перенести индикатор SUDO в комбинированный сегмент fileinfo (см. .vim/autoload/Powerline/Segments.vim), тоже не очень хорошо - придется использовать серый фон;
  4. сделать так, чтобы фон индикатора paste_indicator всегда соответствовал фону следующего постоянного сегмента mode_indicator. В этом случае цвет стрелочных артефактов будет совпадать с цветом фона следующего сегмента и, соответственно, они должны бесследно исчезнуть;
Лично я воспользовался последним вариантом и переопределил paste_indicator в .vim/autoload/Powerline/Colorschemes/default.vim как
    \
    \ Pl#Hi#Segments(['paste_indicator'], {
        \ 'n': ['brightestred''brightgreen', ['bold']],
        \ 'i': ['brightestred''white', ['bold']],
        \ 'v': ['brightestred''brightorange', ['bold']],
        \ 'r': ['brightgreen''brightred', ['bold']],
        \ 's': ['brightestred''gray5', ['bold']],
        \ }),
После перзагрузки кэша Powerline и запуска svim я получил следующие картинки: 


В нормальном режиме при установленном paste это выглядит так:

 

воскресенье, 25 ноября 2012 г.

Шрифты Powerline в linux консоли

Отвечая на вопрос о шрифтах Powerline в linux консоли (см. комментарии к этому посту), я привел варианты, как этого можно добиться. Ни один вариант для меня не подошел в силу разных обстоятельств. Добавлять новые символы в консоли оказалось вообще не просто и какого-то единого алгоритма попросту не существует. Но мне все-таки удалось с этим справиться, и здесь я хочу поведать об этой истории успеха. Все, что здесь будет сказано, относится к Fedora 17, для других дистрибутивов действия могут слегка отличаться.


Картинка большая и кликабельная. Символы из Powerline видны в статусной строке vim (там где им и положено находиться), а также внутри присваиваемого значения переменной PROMPTLINE в функции proml редактируемого файла .bashrc (курсор находится между словами function и proml, создавая впечатление, что это одно слово, соединенное символом подчеркивания). Цветов в статусной строке нет по той простой причине, что в дефолтной схеме Powerline используется 256-цветная палитра, которая не работает в linux консоли. Так что если вы хотите нормальную цветную статусную строку Powerline в linux консоли, вам придется изменить дефолтную цветовую схему Powerline, или создать новую (схемы находятся в директории $HOME/.vim/autoload/Powerline/Colorschemes/). Также хочу отметить, что эта картинка была получена с помощью замечательной программы fbgrab из пакета fbcat, который я взял отсюда (кликнув на строке Fedora 17).

Итак, что нам понадобится для создания нового шрифта с символами из Powerline для linux консоли? Прежде всего, понимание того, что нам нужен шрифт с весьма специфичным форматом PSF, который, хотя и поддерживает Unicode mapping, все же не может содержать более 512 символов. В Fedora 17 psf шрифты находятся в директории /lib/kbd/consolefonts/. При включении режима Unicode в консоли c помощью команды unicode_start, попросту загружается новый шрифт с необходимыми символами, в частности у меня в Fedora это /lib/kbd/consolefonts/UniCyr_8x16.psf.gz, который содержит всего 256 символов. Если в вашей консоли используется шрифт terminus, то название файла будет, естественно, другим. Таблица соответствия с символами Unicode прописана внутри файла шрифта, и просмотреть ее можно с помощью команды psfgettable. Таким образом, задача сводится к созданию нового psf файла, в который добавлены символы из Powerline, при этом общее количество символов в файле не должно превышать 512. В дальнейшем, в качестве базового шрифта я буду использовать UniCyr_8x16.psf.

Что нам понадобится из программного обеспечения? Первое - программа otf2bdf для создания шрифта в промежуточном формате bdf: ее в Fedora 17 можно установить с помощью yum. Второе - программа gbdfed для конвертации шрифта bdf в формат psf: она также устанавливается с помощью yum. Третье - пакет PSF tools для манипуляции с psf шрифтами: его я скачал отсюда. Четвертое - удобный текстовый редактор (например, vim) для удаления артефактов конвертации в текстовом представлении шрифта. Пятое - исходный файл с базовыми кириллическими символами, в который мы внедрим новые символы Powerline, как я уже говорил это будет файл UniCyr_8x16.psf из директории /lib/lbd/consolefonts/.

Итак, приступим. Первое, что мы сделаем - это выделим все символы из Powerline (всего их девять) в отдельный шрифт в формате bdf. Эта задача вполне по плечу программе otf2bdf. Исходный файл должен быть получен с помощью программы  fontpatcher из плагина Powerline и иметь формат otf или ttf (см. подробности здесь). У меня данный файл называется DejaVuSansMonoForPowerline.ttf. Программа otf2bdf должна знать, какие символы нам нужны, а также соответствующие им значения Unicode. Для этого мы создадим вспомогательный файл dvusmpl.bdfmap (название не имеет значения), в котором зададим этот маппинг:
REGISTRY ISO10646
ENCODING 1
0x60 0x2B60
0x61 0x2B61
0x62 0x2B62
0x63 0x2B63
0x64 0x2B64
0x80 0x2B80
0x81 0x2B81
0x82 0x2B82
0x83 0x2B83
Строки REGISTRY и ENCODING могут содержать достаточно произвольные значения: в нашем случае они не будут важны. Далее прописан маппинг номер символа : значение Unicode. Номера символов в принципе тоже не имеют значения, однако здесь я сопоставил их со значениями Unicode, которые соответствуют символам Powerline. Первая попытка:
otf2bdf -v -c M -l '96_131' -o dvusmpl.bdf -m dvusmpl.bdfmap DejaVuSansMonoForPowerline.ttf
не увенчается успехом из-за размера сгенерированного шрифта, который окажется 12x20 вместо 8x16 (bdf формат имеет текстовое представление и размер шрифта можно найти в строке FONTBOUNDINGBOX в заголовке файла). otf2bdf позволяет настроить размер шрифта с помощью опций -rh и -rv, значения которых, однако, соответствуют не количеству пикселов по горизонтали и вертикали, а количеству точек на дюйм, поэтому поиск подходящих значений - задача творческая. После нескольких попыток я наконец подобрал подходящие значения для этих опций:
otf2bdf -v -c M -rh 66 -rv 86 -l '96_131' -o dvusmpl.bdf -m dvusmpl.bdfmap DejaVuSansMonoForPowerline.ttf
Опция -c M указывает на то, что мы хотим создать моноширинный шрифт, а опция -l '96_131' задает диапазон символов для генерации (десятиричное число 91 соответствует шестнадцатиричному 0x60, a 131 - 0x83).

Теперь у нас есть файл c символами Powerline в формате bdf. Открываем его в программе gbdfed, убеждаемся, что все 9 символов на месте (скорее всего gbdfed разобьет шрифт на 2 страницы, при этом первые 5 символов окажутся на первой, а оставшиеся 4 - на второй), и экспортируем его в формат PSF (в меню File программы). После экспорта файла у нас появится файл dvusmpl.psfu.

Следующий шаг - переводим файл dvusmpl.psfu в текстовый формат с помощью программы psf2txt из PSF Tools.
psf2txt dvusmpl.psfu dvusmpl.txt
Открываем dvusmpl.txt в текстовом редакторе и правим псевдографические изображения символов по своему вкусу: это необходимо, так как odf2bdf в процессе масштабирования шрифта исказила исходные символы (главным образом стрелки). Поскольку я все это уже проделал, то результат (с дополнительными правками - см. ниже) проще скачать отсюда.

Теперь берем исходный PSF файл UniCyr_8x16.psf.gz, раззиповываем его и переводим в текстовый формат:
psf2txt UniCyr_8x16.psf UniCyr_8x16ForPowerline.txt
В конец нового файла UniCyr_8x16ForPowerline.txt вставляем содержимое файла dvusmpl.txt, меняем  строки // Character 0 .. 8 во вставленном участке на // Character 256 .. 264. Также добавляем во вставленном участке строки с Unicode информацией для каждого отдельного символа таким же образом, как это сделано для символов исходного psf шрифта. Если вы скачали выложенный мною файл dvusmpl.txt, то достаточно просто добавить его в конец файла UniCyr_8x16ForPowerline.txt, так как все необходимые изменения в нем уже есть. Теперь идем в начало файла, ищем строку Length: 256 и заменяем ее на Length: 265 (мы ведь добавили 9 новых символов).

Переводим UniCyr_8x16ForPowerline.txt в формат psf c помощью программы txt2psf из PSF Tools:
txt2psf UniCyr_8x16ForPowerline.txt UniCyr_8x16ForPowerline.psf
Можно убедиться, что новые символы присутствуют в UniCyr_8x16ForPowerline.psf:
psfgettable PowerLineSymbols1.psf | grep -i 2b80
Зипуем файл и кладем его в директорию /lib/kbd/consolefonts/. Логинимся в виртуальной консоли и загружаем новый шрифт:
unicode_start UniCyr_8x16ForPowerline
Теперь открываем vim и смотрим, присутствуют ли в статусной строке символы из Powerline.

Если есть желание загружать новый шрифт каждый раз при входе в систему из виртуальной консоли, то можно добавить строку unicode_start UniCyr_8x16ForPowerline для linux консоли в какой-нибудь файл из директории /etc/profile.d/ (см. подробно здесь). Кроме того, теперь и в linux консоли вы сможете сделать приглашение командной строки более привлекательным (см. здесь).

Update. Выяснилось, что дефолтный консольный Unicode шрифт в Fedora 17 - это latarcyrheb-sun16 (загляните внутрь скрипта /usr/bin/unicode_start и поймете почему). В шрифте определены 512 символов, поэтому, если брать его за основу, следует не добавлять дополнительные символы, а заменить те из существующих, которые вы вряд ли будете использовать, например в позициях 460 - 488 находятся символы арабского алфавита, и если вы не читаете тексты на арабском, то можете смело вставлять новые символы куда-нибудь внутрь этого диапазона.

Последние изменения. Картинка:


Все цвета в статусной строке присутствуют, Unicode символы на месте (в т.ч. стрелочки в окне tagbar), я специально вышел из vim, чтобы показать, что в строке приглашения тоже находятся символы из Powerline.

За базовый шрифт я взял /lib/kbd/consolefonts/latarcyrheb-sun16.psfu.gz. Распаковываем, переводим в текст с помощью psf2txt, заменяем символы с 460 по 472 этим. Переводим обратно в psf:
txt2psf latarcyrheb-sun16.txt latarcyrheb-sun16_vim-unicode.psfu
Зипуем latarcyrheb-sun16_vim-unicode.psfu и кладем в /lib/kbd/consolefonts/. Файл /etc/profile.d/console_unicode.sh теперь выглядит так:
if [ "$TERM" = "linux" ]; then
    unicode_start latarcyrheb-sun16_vim-unicode
    export CONSOLEFONT_HAS_VIM_UNICODE_SYMB=1
fi
Изменения в файле $HOME/.bashrc:
case $COLORTERM in
    gnome*|mate*|konsole*)
        TERM=xterm-256color
        ;;
esac

[ -n "$XTERM_SHELL" ] && COLORTERM=xterm-256color

function proml
{
    case $COLORTERM in
        gnome*|mate*|konsole*)
            local PROMPTLINE="\[\033[38;5;167m\]\$(date +%d/%m/%y\ %H:%M)⮁⮁ \
\[\033[38;5;173m\]\u@\[\033[38;5;140m\]\h⮁⮁\[\033[38;5;173m\] \W \[\033[0m\] "
            local PROMPTLINE2='\[\033[38;5;196m\]⮀\[\033[0m\] '
            ;;
        xterm*)
            local PROMPTLINE="\[\033[38;5;167m\](\$(date +%d/%m/%y\ %H:%M))\
\[\033[38;5;173m\][\u@\[\033[38;5;140m\]\h\[\033[38;5;173m\] \W]$\[\033[0m\] "
            local PROMPTLINE2='\[\033[38;5;196m\]>\[\033[0m\] '
            ;;
        *)
            if [ "$TERM" = "linux" ] && \
               [ -n "$CONSOLEFONT_HAS_VIM_UNICODE_SYMB" ] ; then
                local PROMPTLINE="\[\033[32m\]\$(date +%d/%m/%y\ %H:%M)⮁⮁ \
\[\033[0m\]\u@\[\[\033[1;34m\]\h\[\033[0m\]⮁⮁\[ \W \033[32m\]\[\033[0m\] "
                local PROMPTLINE2='\[\033[31m\]⮀\[\033[0m\] '
            else
                local PROMPTLINE="(\$(date +%d/%m/%y\ %H:%M))[\u@\h \W]$ "
                local PROMPTLINE2=''
            fi
            ;;
    esac
    PS1=$PROMPTLINE
    PS2=$PROMPTLINE2
}

proml
unset proml
Изменения в $HOME/.vimrc:
" ---- Powerline settings
" ----
" disable Unicode symbols in linux console if font does not support them
let g:DisableUnicodeSymbols = &term =~? '^linux' &&
            \ empty($CONSOLEFONT_HAS_VIM_UNICODE_SYMB)

let g:Powerline_theme = 'default'

" solarized theme is suitable for linux console
if &t_Co < 256
    let g:Powerline_colorscheme = 'solarized'
else
    let g:Powerline_colorscheme = 'default'
endif

" fancy symbols need patched font!
if g:DisableUnicodeSymbols
    let g:Powerline_symbols = 'compatible'
else
    let g:Powerline_symbols = 'fancy'
endif

" do not use Powerline in simple console terminals
let g:DisablePowerline = &term =~? '^linux' && 0

if g:DisablePowerline
    let g:Powerline_loaded = 0
endif

if !empty($TMPDIR)
    let g:Powerline_cache_file = $TMPDIR."/Powerline_".$USER."_".
                \ g:Powerline_theme."_".g:Powerline_colorscheme."_".
                \ g:Powerline_symbols.".cache"
else
    let g:Powerline_cache_file = '/tmp/Powerline_'.$USER.'_'.
                \ g:Powerline_theme.'_'.g:Powerline_colorscheme.'_'.
                \ g:Powerline_symbols.'.cache'
endif
(я сюда еще правильную обработку кэша цветовой схемы Powerline добавил).

Да, и самое главное - патч для  цветовой схемы solarized.vim. Без него статусная строка Powerline в консоли правильно работать не будет!
--- autoload/Powerline/Colorschemes/solarized.vim   2012-11-27 13:46:28.923529118 +0400
+++ autoload/Powerline/Colorschemes/solarized.vim.new   2012-11-27 13:35:09.794349678 +0400
@@ -3,19 +3,19 @@
 " N = no focus
 " 16 hex colors as defined on http://ethanschoonover.com/solarized
 call Pl#Hi#Allocate({
-  \ 'base03'  : [8,   0x002b36],
+  \ 'base03'  : [&t_Co > 8 ? 8 : '0*',   0x002b36],
   \ 'base02'  : [0,   0x073642],
-  \ 'base01'  : [10,  0x586e75],
-  \ 'base00'  : [11,  0x657b83],
-  \ 'base0'   : [12,  0x839496],
-  \ 'base1'   : [14,  0x93a1a1],
+  \ 'base01'  : [&t_Co > 8 ? 10 : '2*',  0x586e75],
+  \ 'base00'  : [&t_Co > 8 ? 11 : '6*',  0x657b83],
+  \ 'base0'   : [&t_Co > 8 ? 12 : '1*',  0x839496],
+  \ 'base1'   : [&t_Co > 8 ? 14 : '3*',  0x93a1a1],
   \ 'base2'   : [7,   0xeee8d5],
-  \ 'base3'   : [15,  0xfdf6e3],
+  \ 'base3'   : [&t_Co > 8 ? 15 : '7*',  0xfdf6e3],
   \ 'yellow'  : [3,   0xb58900],
-  \ 'orange'  : [9,   0xcb4b16],
+  \ 'orange'  : [&t_Co > 8 ? 9 : '4*',   0xcb4b16],
   \ 'red'     : [1,   0xdc322f],
   \ 'magenta' : [5,   0xd33682],
-  \ 'violet'  : [13,  0x6c71c4],
+  \ 'violet'  : [&t_Co > 8 ? 13 : '5*',  0x6c71c4],
   \ 'blue'    : [4,   0x268bd2],
   \ 'cyan'    : [6,   0x2aa198],
   \ 'green'   : [2,   0x859900],
(зафайлил баг в Powerline, надеюсь починят).

четверг, 1 ноября 2012 г.

Строка приглашения shell со шрифтами из Powerline

Случайно наткнулся в github на проект powerline-bash, в котором, как я понимаю, предпринята попытка перенести модель статусной строки из плагина для vim Powerline в строку приглашения shell (shell prompt). Идея интересная, однако использование цветных бэкграундов для шрифта противопоказано в моей псевдопрозрачной консоли: результат, скорее всего, будет выглядеть убого. Однако мысль о том, чтобы использовать символы стрелок из шрифта Powerline в строке приглашения, показалась мне перспективной. За сим я решил воплотить ее в жизнь. Результат представлен на картинке.


Полые и закрашенные угловые стрелки  на картинке - это и есть дополнительные символы из Powerline. Полой стрелке соответствует символ Unicode 2b81, закрашенной - 2b80. О том, как установить шрифт Powerline (хотя это совсем не шрифт, а просто дополнительные символы в вашем любимом шрифте, и термин шрифт Powerline - неверная, но удобная замена), я рассказывал здесь. Специально для пользователей Fedora, которые используют шрифты из репозитория Infinality и собирают шрифт Powerline с помощью fontpatcher, хочу напомнить: используйте не стандартный пакет fontforge, а fontforge-infinality!

После установки шрифта добавляем в .bashrc строки
case $COLORTERM in
    gnome*|mate*|konsole*)
        TERM=xterm-256color
        ;;
esac

[ -n "$XTERM_SHELL" ] && COLORTERM=xterm-256color

function proml
{
    case $COLORTERM in
        gnome*|mate*|konsole*)
            local PROMPTLINE="\[\033[38;5;167m\]\$(date +%d/%m/%y\ %H:%M)⮁⮁ \
\[\033[38;5;173m\]\u@\[\033[38;5;140m\]\h⮁⮁\[\033[38;5;173m\] \W \[\033[0m\] "
            local PROMPTLINE2='\[\033[38;5;196m\]⮀\[\033[0m\] '
            ;;
        xterm*)
            local PROMPTLINE="\[\033[38;5;167m\](\$(date +%d/%m/%y\ %H:%M))\
\[\033[38;5;173m\][\u@\[\033[38;5;140m\]\h\[\033[38;5;173m\] \W]$\[\033[0m\] "
            local PROMPTLINE2='\[\033[38;5;196m\]>\[\033[0m\] '
            ;;
        *)
            local PROMPTLINE="(\$(date +%d/%m/%y\ %H:%M))[\u@\h \W]$ "
            local PROMPTLINE2=''
            ;;
    esac
    PS1=$PROMPTLINE
    PS2=$PROMPTLINE2
}

proml
unset proml
В данном коде присутствуют символы Unicode 2b80 и 2b81. Если вы еще не установили шрифт Powerline, то они, скорее всего, не будут похожи на стрелки на вашем экране, а вероятно будут заменены вопросительными знаками или какими-нибудь кракозябрами. Кстати, если вам придется вставлять юникодные символы в vim, то делается это очень просто: в режиме ввода набираем Ctrl-V, затем u, а затем соответствующее символу значение (например 2b80).

Теперь вводим в командной строке
. ~/.bashrc
и наслаждаемся результатом.

воскресенье, 15 января 2012 г.

vim: плагин Powerline

Вчера установил новый плагин Powerline. Этот плагин позволяет сделать статусную строку vim весьма привлекательной, с возможностью легко различать текущий режим. Ниже я привожу два снимка окна терминала с двумя открытыми файлами и буфером tagbar справа (на официальном сайте Powerline тоже есть скриншоты, см. здесь). Активный буфер расположен внизу, соответственно Powerline подсвечивает его статусную строку ярче и информативнее. На первом снимке буфер находится в нормальном режиме, на втором - в режиме ввода.


Как видно на снимках, Powerline поддерживает tagbar, но не совсем из коробки, но об этом позже. Сначала о том, как настроить Powerline, чтобы он показывал статусную строку в максимально привлекательном виде.

Просто установить Powerline для этого недостаточно. Стандартные консольные шрифты не содержат этих привлекательных символов - угловых стрелок, символа FT и др., которые видны на приведенных снимках. Эти символы определены в файле PowerlineSymbols.sfd в директории fontpatcher/ плагина. В той же директории находится файл README.rst, в котором приведена инструкция для настройки шрифта консоли. Я попробую пересказать ее своими словами и добавить некоторые дополнительные сведения, которые я почерпнул при установке нового шрифта. Если вы боитесь или не хотите устанавливать новый шрифт, то можно использовать и стандартную настройку Powerline по умолчанию (она называется compatible), в этом случае вместо привлекательных стрелочек вы увидите простые консольные символы '|'. Есть еще один вариант настройки, который не предусматривает изменения стандартного шрифта, но делает статусную строку все же немного привлекательнее: это использование стандартных символов Unicode. Для этого поместите в файл .vimrc настройку
let g:Powerline_symbols = 'unicode'
Вернемся к установке нового шрифта. Хотя новый шрифт - это громко сказано. Фактически следует просто взять тот шрифт, который используется в вашей консоли и добавить в него новые символы из PowerlineSymbols.sfd с помощью программы fontpatcher из директории fontpatcher/. fontpatcher использует FontForge, поэтому следует предварительно установить этот пакет в вашу систему. Лично я использую шрифт DejaVu Sans Mono, который в моей системе (Fedora 16) находится в директории /usr/share/fonts/dejavu/. Чтобы добавить новые символы в этот шрифт, перейдем в директорию fontpatcher/ и выполним команду:
./fontpatcher --symbol-font PowerlineSymbols.sfd /usr/share/fonts/dejavu/DejaVuSansMono.ttf
Теперь в этой директории должен появиться новый файл DejaVuSansMono-Powerline.otf, который следует поместить в директорию $HOME/.fonts/. После этого от имени суперпользователя запускаем команду
fc-cache -vf
Теперь следует установить данный шрифт в качестве шрифта терминала. Заходим в настройки терминала и находим диалог выбора шрифта. fontpatcher добавляет в имя шрифта строку for Powerline, соответственно в моем случае шрифт будет называться DejaVu Sans Mono for Powerline. В терминале XFCE новый шрифт будет доступен сразу, в konsole - не знаю, ну а в случае gnome-terminal из Gnome 3 придется выполнить массу неочевидных и логически необоснованных действий (как это заведено в Gnome 3). Вы не найдете нового шрифта в диалоге выбора gnome-terminal. Я не знаю, может быть есть лучший способ, но я просто решил сделать новый шрифт системным Мonospace шрифтом в Gnome 3. И даже это сделать не так-то просто: для начала нужно установить (по крайней мере в Fedora 16) пакет gnome-tweak-tool, затем собственно запустить gnome-tweak-tool и в диалоге выбора Monospace шрифта выбрать DejaVu Sans Mono for Powerline. После этого действия выбор данного шрифта останется недоступным в gnome-terminal (ну чего еще-то ему не хватает? :) ), зато теперь можно выбрать Системный моноширинный шрифт и им, наконец-то, окажется наш пропатченный DejaVu Sans Mono.

Огромный плюс в установке нового шрифта - это то, что рендерится он качественнее, чем оригинал, вот это сюрприз!

Для правильного отображения новых символов в .vimrc нужно добавить строку
let g:Powerline_symbols = 'fancy'
Однако, если вы успели поэкспериментировать с другими значениями g:Powerline_symbols, то вам придется удалить кеш-файл, который находится в /tmp/Poweline.cache (либо, если у вас установлена переменная среды $TEMP, в $TEMP/Powerline.cache).

Еще одна тонкость - возможно вы заметите, что при переходе из режима ввода в нормальный режим путем нажатия клавиши Esc, обновление статусной строки будет задерживаться примерно на секунду. Чтобы избежать этого, поместите в .vimrc строку
set timeout timeoutlen=1000 ttimeoutlen=50
(в данном случае важно установить относительно небольшое значение ttimeoutlen, например 50 миллисекунд, значение timeoutlen для данной проблемы не играет роли, и, если вы не знаете, что это такое, то вообще не указывайте здесь timeoutlen).

И еще одна тонкость. По умолчанию, если в vim открыто единственное окно, то статусная строка вообще не показывается. Чтобы статусная строка присутстствовала всегда, добавьте в .vimrc строку
set laststatus=2
Теперь вернемся к tagbar. Powerline поддерживает статусную строку tagbar - это видно на приведенных скриншотах. Однако работает это криво. Во-первых, статусная строка tagbar не изменяется при первом открытии окна tagbar; во-вторых, при переходе на тег из окна tagbar в окно целевого буфера, статусные строки также не перерисовываются, несмотря на то, что активное окно изменилось. Проблема в том, что в самый ответственный момент, когда происходят события открытия окна tagbar и перехода на новую метку, в коде tagbar (в функциях файла autoload/tagbar.vim) устанавливаются значения опции eventignore в all. Соответственно все автокоманды, определенные в Powerline (а также и в других плагинах, и любые пользовательские) игнорируются. Мы не станем убирать установку eventignore в all, вдруг это сделано неспроста и что-нибудь сломается. Мы просто введем понятие хуков для трех событий: отрисовки статусной строки при запуске нового окна tagbar, покидания окна tagbar при переходе на метку, и перехода в целевое окно из окна tagbar при переходе на метку. Соответственно, названия хуков будут g:tagbar_statusline_hook, g:tagbar_leave_hook, g:tagbar_dstwin_enter_hook. Хуки следует разместить, соответственно, в функциях s:InitWindow() и s:JumpToTag() в файле autoload/tagbar.vim. Вот простейший патч (относительно версии tagbar 2.3.0):
--- tagbar.vim  2011-12-24 09:14:54.000000000 +0400
+++ tagbar.vim.new  2012-01-15 18:07:07.691191871 +0400
@@ -1478,17 +1478,21 @@
     " Reset fold settings in case a plugin set them globally to something
     " expensive. Apparently 'foldexpr' gets executed even if 'foldenable' is
     " off, and then for every appended line (like with :put).
     setlocal foldmethod&
     setlocal foldexpr&
 
-    " Earlier versions have a bug in local, evaluated statuslines
-    if v:version > 701 || (v:version == 701 && has('patch097'))
-        setlocal statusline=%!TagbarGenerateStatusline()
+    if exists('g:tagbar_statusline_hook')
+        execute g:tagbar_statusline_hook
     else
-        setlocal statusline=Tagbar
+        " Earlier versions have a bug in local, evaluated statuslines
+        if v:version > 701 || (v:version == 701 && has('patch097'))
+            setlocal statusline=%!TagbarGenerateStatusline()
+        else
+            setlocal statusline=Tagbar
+        endif
     endif
 
     " Script-local variable needed since compare functions can't
     " take extra arguments
     let s:compare_typeinfo = {}
 
@@ -2427,13 +2431,19 @@
     let eventignore_save = &eventignore
     set eventignore=all
 
     " This elaborate construct will try to switch to the correct
     " buffer/window; if the buffer isn't currently shown in a window it will
     " open it in the first window with a non-special buffer in it
+    if exists('g:tagbar_leave_hook')
+        execute g:tagbar_leave_hook
+    endif
     wincmd p
+    if exists('g:tagbar_dstwin_enter_hook')
+        execute g:tagbar_dstwin_enter_hook
+    endif
     let filebufnr = bufnr(taginfo.fileinfo.fpath)
     if bufnr('%') != filebufnr
         let filewinnr = bufwinnr(filebufnr)
         if filewinnr != -1
             execute filewinnr . 'wincmd w'
         else
Теперь определим хуки в .vimrc:
let g:tagbar_statusline_hook = 'call Pl#UpdateStatusline(0)'
let g:tagbar_leave_hook = 'call Pl#UpdateStatusline(0)'
let g:tagbar_dstwin_enter_hook = 'call Pl#UpdateStatusline(1)'
После этого tagbar будет правильно работать с Powerline.