Ansible: настраиваем zsh терминал с antigen, autosuggestions, fzf и красивым prompt одной командой

    Я провожу в терминале много времени, поэтому хочется, чтобы все было красиво, быстро и удобно. Из этого рождается постоянное желание его настраивать, пробовать разные плагины. Шеллом я выбрал для себя zsh лет 5 назад, пару лет назад нашел oh-my-zsh для его удобной настройки.


    Со временем к этому конфигу добавились некоторые сбоку торчащие части в виде powerline и percol.


    Недавно я решил пересобрать все так, чтобы избавиться от ненужных плагинов, добавить нужные, сделать легкую установку и обновление. В итоге появилась роль ansible-role-zsh, которая полностью настраивает терминалы на локалке и на моих серверах.


    Особенности:


    • устанавливается одной командой (кроме шрифта и темы вашего терминального клиента)
    • быстро загружается, быстро работает
    • полностью настраивается через ansible, ~/.zshrc
    • полностью локальная (в систему ничего не ставится, все хранится в ~/.oh-my-zsh)
    • оставляет возможность юзеру вносить свои настройки через ~/.zshrc.local
    • одинаково работает на macOS, старом Debian, Ubuntu, CentOS
    • нормально выглядит на разных цветовых схемах (но лучше всего на Solarized Dark)
    • встроенная подсветка синтаксиса (помогает реже ошибаться и лучше читать длинные команды)
    • автодополнение по истории команд (помогает реже нажимать Ctrl+R)
    • отображение времени для долго выполняемых команд (помогает реже использовать time)

    Демонстрация фич за 1 минуту:





    Раньше я пользовался powerline, который отвечал за command prompt (строку состояния) и percol для интерактивного поиска. Обе утилиты написаны на python.


    Они хороши, когда я нашел percol, скорость работы в терминале сразу выросла, я радовался этому в блоге, но ставилось это все не очень красиво (bash инсталлером), имело некоторые проблемы при работе нескольких юзеров с красивыми терминалами на одном сервере.


    Также в некоторых случаях проявлялись недостатки утилит: терминал грузился с небольшой задержкой (около 1 секунды), percol тупил на больших объемах текста.


    Питоновские утилиты хотели, чтобы я их настраивал через отдельные конфиги. Мне отдельные конфиги поддерживать не хотелось, поэтому я пользовался ими с настройками по умолчанию, не скажу, что они были плохие, но можно было и получше.


    По этим причинам я поискал, чем их можно заменить и нашел.


    fzf, замена Percol


    Fuzzy finder написан на Go, имеет кучу звездочек, судя по описанию, заточен на работу в Vim, но и в других местах работает.


    При выборе смотрел еще на peco, они похожи, оба написаны какими-то японцами на Go, я выбрал fzf по следующим критериям:


    • больше контрибьюторов, вообще пульс проекта бьется примерно в 2 раза чаще
    • заточен под vim и tmux, при этом хорошо работает и в обычном терминале
    • настраивается через параметры командной строки и переменные окружения, а не через отдельный конфиг
    • короче на одну букву :)

    У fzf есть некая крутая фича автодополнения разного через **<Tab>, я не проверял, но автор плагина fzf-zsh пишет, что он конфликтует с zsh-autosuggestions, я ему верю.


    Powerlevel9k, замена Powerline


    Тему powerlevel9k я нашел случайно, потом проверил, по запросу на Github powerline zsh он второй (после самого powerline).


    Тема навороченная, позволяет много всего, я воспользовался некоторыми из фич:


    • настройка всего через переменные окружения (сегменты, их расположение, цвета)
    • добавление кастомных сегментов через те же переменные

    Как и powerline, тема требует установки патченных шрифтов powerline fonts, я использую шрифт Droid Sans Mono, 12pt. Шрифт и цветовая схема — две вещи, которые нужно установить вручную.


    zsh-autosuggestions


    Открытие этого плагина для меня сравнимо с открытием percol: скорость набора команд увеличилась.
    Часто бывает нужно набрать команду с теми же параметрами, что и в прошлый раз, или немного с другими параметрами. Плагин выручает в обоих случаях.


    Работает это так: при вводе команды плагин читает историю и дописывает серым последнюю команду из истории, начинающуюся так же.


    Если нажать Enter, выполнится ваша команда, а не из автодополнения (это хорошо, случайно вызвать не ту команду будет сложно, хотя у некоторых автодополнений бывают такие проблемы). Чтобы подставить дополненную команду, нужно нажать кнопку, забинденную на действие autosuggest-accept, по умолчанию это →.


    Но до стрелочки вправо постоянно тянуться неудобно, поэтому я сначала забиндил автодополнение на backtick (обратную кавычку, которая слева от единицы). Это было очень удобно: прямо рядом с Tab и работает похоже на Tab. Но позже выяснилось, что это ломает работу Midnight Commander: на одних системах он перестал переключать путь во внутреннем шелле (что полезно: через mc переходим в нужную папку, нажимаем Ctrl+O, вводим команду, выходим из внутреннего шелла, или наоборот бывает удобнее перейти в папку через шелл, а потом произвести действия в mc), на других системах mc вообще зависал через пару переходов по папкам. Я погуглил проблему, в трекере mc есть такой глюк, в последней версии 4.8.18 зависания убрались, но путь так и не стал меняться, поэтому я стал пробовать другие хоткеи: Ctrl+Space, Ctrl+I, все они так или иначе глючили.


    В итоге пришел к такому: я сам mc пользуюсь редко, поэтому на всех системах, где бываю не только я, я забиндился на Ctrl+U, а на личных — еще и на кавычку. В плейбуке забиндено только на стрелочку.


    Еще в ansible-role-zsh работа плагина ограничена 15 символами, то есть через 15 символов он перестает предлагать команды.


    Это сделано для того, чтобы убрать задержки при копипасте команд в терминал (при вводе самостоятельно я задержек не ощущаю, но при вставке из буфера больших команд это заметно, похоже на то, как будто вставка не сработала).


    zsh-syntax-highlighting


    Про этот плагин можно сказать не особо много: подсвечивает текущую введенную команду, раскрашивая на лету.


    Главный плюс в том, что вы видите, что опечатались по красному цвету слова. Не скажу, что это must have, но удобнее становится.


    В то же время у плагина есть сразу несколько косяков.


    На системах, где zsh < 4.3.17, вызывает крах терминальной сессии, поэтому в плейбуке есть защита от активации плагина на таких системах. Случай редкий, я сделал это ради Debian Squeeze.


    Плагин должен подключаться последним, а не то не знаю что будет и знать не хочу.


    Конфликтует с zsh-autosuggestions, проявляется в вылетании сессии при попытке повторно применить конфиг .zshrc.


    Про это есть соответствующий issue и автор zsh-autosuggestions говорит, что исправление уже в devel ветке, я не проверял, но если это так, после релиза v0.3.4 должно все исправиться.


    В плейбуке для этого есть фикс, так что конфликт устранен.


    zsh-command-time


    Пока наводил порядок в этом проекте, реализовал одну из своих давних хотелок: вывод времени выполнения для команд, которые выполняются долго. До этого я либо смотрел на часы в правом углу терминала и сравнивал с часами в предыдущей команде, либо сразу запускал команду с time. Теперь этого делать не надо.


    Внешний вид темы в разных цветовых схемах


    Я использую цветовую схему Solarized Dark, но чтобы не огорчать коллег, которые заходят на настроенные мной сервера, я проверил, как выглядит терминал на стандартной палитре Putty, на стандартной палитре Ubuntu, на встроенных темах iTerm:





    Установка


    Итак, если вам понравилось, предлагаю сначала посмотреть работу вживую, в Vagrant:


    git clone https://github.com/viasite-ansible/ansible-role-zsh.git
    vagrant up

    Перед установкой на рабочую систему внимательно прочитайте это:


    • Роль не установится, если у вас уже есть директория ~/.oh-my-zsh, переименуйте ее, если она у вас есть.
    • Роль затрет ваш ~/.zshrc, сделайте бекап!
    • После применения роли, если хотите и дальше управлять терминалом через ansible, нужно писать свои настройки либо в переменные плейбука, либо в ~/.zshrc.local, этот файл инклюдится в конце ~/.zshrc и ansible его не трогает.

    Если все устраивает, можно установить роль через ansible-galaxy:


    ansible-galaxy install viasite-ansible.zsh

    Потом создать плейбук вроде такого:


    hosts: all
    vars:
      zsh_autosuggestions_bind_key: "^U"
    roles:
      - viasite-ansible.zsh

    Сохранить, например, в zsh.yml. После этого роль можно применить к локальному юзеру:


    ansible-playbook -i "localhost," -c local zsh.yml

    Как применить к другим юзерам и серверам пользователи ansible думаю разберутся.


    Проверено на Debian 6, Ubuntu 14.04, Ubuntu 16.04, macOS 10.12, CentOS 7.


    Все доступные переменные не стал выносить в README.md, их можно посмотреть
    в defaults/main.yml.


    Выводы


    Я понимаю, что конфиг терминала — очень личная вещь, не уверен, что будет много желающих воспользоваться именно моей ansible ролью, поэтому я постарался сделать ее максимально настраиваемой. Если будут желающие использовать, пожалуйста, оставляйте issues.


    Конечно, это не последний конфиг, например, пока я писал эту статью, я нашел antigen, менеджер плагинов для zsh, который написан по аналогии с Vundle для Vim, заточен на работу в паре с oh-my-zsh и избавляет от ручной установки плагинов. Это как раз одна из проблем, которую я решал написанием роли. Поделитесь, кто пользовался.
    UPD 03.04.2017: переписал роль с использованием antigen.


    В комментах хотелось бы найти новых вкусных плагинов, пожалуйста, напишите, какие плагины вызвали у вас чувство "как я жил без этого раньше?"


    UPD: добавилась поддержка CentOS, спасибо, BeeVee!

    Поделиться публикацией
    Ой, у вас баннер убежал!

    Ну. И что?
    Реклама
    Комментарии 20
    • +3

      Спасибо, интересная штука!


      Роль затрет ваш ~/.zshrc, сделайте бекап!

      Можно же из роли бэкап сделать:


      - name: Write .zshrc config
        template:
          src: zshrc.j2
          dest: "{{ zsh_user_config }}"
          owner: "{{ zsh_user }}"
          group: "{{ zsh_user_group }}"
          backup: yes
      • 0
        Да, точно, надо бы добавить, изначально я для себя делал, предполагалось, что бекап старого конфига не нужен.
        • 0

          Я что-то не сообразил, надо было просто реквест вам кинуть. ) Вижу, что уже всё исправлено.

          • 0

            да, и после этого у меня вот что стало:



            Вообще статья немного устарела с тех пор, теперь роль работает поверх antigen, добавилось еще несколько плагинов, актуальная информация в readme.

      • 0
        Большое спасибо за статью. Узнал из нее о существовании fzf =)

        Сам когда то тоже любил обвешать шелл кучей плагинов, но в итоге забывал пользоваться доброй половиной из них, а подтупливающий терминал начинал раздражать. Вернулся к bash с кучкой алиасов и git-prompt.sh
        Ну и теперь вот fzf добавился.
        • 0
          Да, подтупливания были одной из причин переписать свой конфиг. Текущая скорость меня устраивает, теперь надо до подтупливающего vim еще добраться.

          А у вас кроме алиасов и fzf ничего интересного нет?
          • 0
            А еще я сегодня узнал, что есть плагины, которые напоминают о плагинах, о которых вы забыли :)
          • 0
            Попробовал плагины zsh-autosuggestions и zsh-syntax-highlighting и сразу же натолкнулся на баг.
            Набираем zsh --version, далее ls потом опять zsh --version (но уже через zsh-autosuggestions). Дальше если нажать вверх то подставиться команда ls но при вводе выполняется не она а zsh --version.
            • 0
              хотя попытался в 5-й раз повторить, теперь не воспроизводится.
              • 0
                удаленный фикс от разработчиков ;)
            • +1

              Видели awesome-zsh-plugins? Это список всего-всего, сязанного с zsh: фреймворки (типа oh-my-zsh), плагины, unit-test (для zsh) и прочее.

              • 0
                Про awesome-zsh не догадался, спасибо, люблю awesom'ы )
              • +1
                Могу еще посоветовать antigen и liquidprompt.
                • 0
                  Крутая тема.
                  Сидел года два на fish, потому что в нем многие фичи из этого поста — из коробки, в частности умная подстановка последней команды, раскраска командной строки, время выполнения команд, ну и т.п.
                  Много слышал про zsh, но я блин слишком ленивый чтобы самому все эти красивости настраивать. :)

                  Попробую обязательно.
                  • 0
                    Интересная статья.

                    Но чем, кроме времени, данный конфиг zsh отличается от fish?
                    • 0

                      Слышал про fish, после вашего коммента посмотрел, расскажу, что я понял за 10 минут.


                      Плюсы fish:


                      • все, что я тут насобирал (кроме fzf и command time) в fish есть из коробки
                      • возможно быстрее грузится (делаю такое предположение, т.к. фичи встроены)

                      Минусы fish:


                      • не POSIX совместим. Что это значит, я узнал здесь
                      • менее популярен (может быть это мне кажется как давнему пользователю zsh)

                      В общем смысла менять zsh на fish не вижу. Тем более менять на серверах, где я не один сижу.

                      • 0
                        > не POSIX совместим
                        Да, это его основной минус.
                        Приходится мудрить со скриптами, и действительно слабо пригодно для групп админов.
                        К сожалению.
                        • 0
                          Насчет популярности: все относительно, как и фломастеры. Тут может играть роль наличия в репозиториях дистрибутивов.

                          Насчет POSIX: спасибо, что подсказали. Уже не раз сталкивался, костылем был запуск bash. Так что переход с fish на zsh имеет смысл.
                      • 0
                        Вместо zsh-command-time можно установить параметр REPORTIME в неотрицательное значение.
                        • 0

                          REPORTTIME, не знал этого. Только это не совсем то, он выводит время user + system, то есть использование процессора, а не время выполнения команды.


                          Например,


                          time find /

                          у меня вывел


                          0.23s user 0.49s system 31% cpu 2.266 total 

                          но т.к. user + system = 0.72, время при REPORTTIME=1 мне не покажут.


                          sleep вообще процессор не потребляет и никогда не будет выведен через REPORTTIME

                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                        Самое читаемое