LaurVas

Мой лончер на базе Dmenu

   bash

Dmenu — это простая, но очень полезная деталь лего утилита. Она читает список из стандартного ввода (stdin) и отображает его на экране в виде вертикального (ключ -l) или горизонтального списка. Пользователь может выбрать один из пунктов стрелками на клавиатуре или печатая символы. Выбранный пункт направляется в стандартный вывод (stdout).

В стандартной поставке вместе с dmenu идёт скрипт dmenu_run для запуска приложений. Ему на вход ничего подавать не надо, он сам возьмёт все бинари из PATH и поместит их в список dmenu, после чего запустит выбранную программу.

Я придумал более удобный скрипт для запуска приложений.

Что не так в стандартном dmenu_run?

  • Все бинари из PATH — это слишком дофига. Консольные утилиты лончером не запускаются, да и графические нужны не все. Когда меню предлагает только то, что реально нужно, двух-трёх первых букв названия утилиты достаточно для её однозначной идентификации, что ускоряет запуск в разы.
  • Нет поддержки алиасов. Создавать скрипты-однострочники и помещать их в PATH как-то не хочется.

Вот мой dmenu_run:

~/bin/dmenu_run
#!/bin/bash
set -o errexit

HISTORY="$HOME/.drun_history"
test -f "$HISTORY" || touch "$HISTORY"
INPUT=$(dmenu $@ < "$HISTORY")
test -n "$INPUT"

# aliases
case "$INPUT" in
    wireshark)
        CMD="wireshark-qt" ;;
    google)
        CMD="xdg-open http://google.com" ;;
    chromium-work)
        CMD="chromium --user-data-dir=$HOME/.config/chromium_work" ;;
    ranger)
        CMD="urxvtc -e ranger" ;;
    *)
        CMD="$INPUT" ;;
esac

# test if CMD exist in $PATH
hash $(echo "$CMD" | cut -f1 -d ' ')

# write input to history
if ! grep -q "$INPUT" "$HISTORY"; then
    echo "$INPUT" >> "$HISTORY"
    sort "$HISTORY" -o "$HISTORY" &
fi

exec $CMD

В моём варианте содержимое dmenu берётся из файла ~/.drun_history, который содержит ранее введённые команды. Такой подход прост в реализации и меню содержит только то, что реально используется. Вначале файл истории пуст и каждую новую команду надо полностью набирать руками. Это одновременно и баг, и фича :) Перед записью в историю выполняется проверка на наличие бинаря в PATH (строчка с hash в коде). Если нет, то ничего не запустится и в историю не попадёт.

Можно вводить команды с аргументом (например firefox localhost:4000) и они будут корректно запускаться.

Можно создавать свои алиасы прямо в скрипте. Несколько примеров уже есть в листинге: wireshark, google, chromium-work. Через алиасы можно запускать консольные утилиты (пример с ranger). Для этого надо запускать свой терминал с ключом -e КОМАНДА. Xterm, urxvt, lxterminal так умеют, я проверил.

Как и оригинальный dmenu_run, мой можно вызывать с аргументами, которые будут определять внешний вид меню.

Я вызываю его так:

$ dmenu_run -y 450 -x 450 -w 1000 -dim 0.5 -l 10 -fn 'Monospace-30:normal'

-y 450 — отступ от верхнего края экрана 450 px, чтобы поле ввода оказалось посередине экрана.
-x 450 — отступ от левого края экрана 450 px для тех ж целей.
-w 1000 — ширина меню 1000 px.
-dim 0.5 — затемняет фон на 50%.
-l 10 — вертикальное меню на 10 строк.
-fn 'Monospace-30:normal' — крупный векторный шрифт.

Результат:

Дефолтные цвета я не стал менять: меню выглядит лаконично и хоршо подходит к стандартной цветовой схеме i3.

Я не представляю себе более удобного лончера, чем этот. Он работает мгновенно.

Пользовательские патчи dmenu

Изначально dmenu создавалось для оконного менеджера dwm командой разработчиков suckless.org. Особенность проектов suckless — простота, аскетичность и минимальный объём кода. Подробнее про философию suckless можно почитать на их сайте.

В оригинальном dmenu нет поддержки векторных шрифтов, нельзя сделать отступы и затемнение фона. Весь этот функционал обеспечивается пользовательскими патчами: поддержка Xft шрифтов, произвольное положение на экране, fuzzy-матчинг, поддержка мыши, и др.

В Archlinux можно найти множество версий dmenu, отличающихся наборами патчей:

  • community/dmenu
  • aur/dmenu-ee-git
  • aur/dmenu-git
  • aur/dmenu-pango-imlib
  • aur/dmenu-xft-wxy-mouse
  • aur/dmenu-xyw-mouse-msel
  • aur/dmenu2
  • aur/dmenuv-git
  • aur/dmenux-git

Я использую dmenu2.

В Debian Stretch и Ubuntu Xenial в официальных репозиториях есть только ванильный dmenu в пакете suckless-tools. И это печально, потому что без пользовательских патчей dmenu уж слишком аскетичный. Мне не удалось найти сторонних репозиториев с патченым dmenu. Если вы их знаете, напишите пожалуйста в комментариях.

Похожий лончер под Windows называется Type and Run.