Многие слышали про тайловые оконные менеджеры, некоторые даже слышали о XMonad. А ребята из Google даже променяли Unity/Gnome на XMonad. Что же это такое, как это настраивать и как с этим жить? Краткий workaround для любителей кастомизировать всё подряд.
Дружище, зачем же оно мне?
Для себя я выделил несколько ситуаций, когда он особенно полезен особенно полезен:
- Рабочий стол ноутбука для разработки. Места нехватает, очень хочется использовать его максимально эффективно;
- Многопониторные рабочие места. XMonad позволяет во всю использовать преимущества нескольких мониторв с помощью xinerma;
- Частое переключение контекстов задач. Например, разработчику часто приходится переключаться между IDE, файловым менеджером, консолью и прочими инструментами. Этот процесс можно ускорить;
- Надоел визуальный шум от стандартных оконных менеджеров.
В общем, меньше слов, больше дела! Если хочешь управляться с рабочим окружением так же ловко, как герой сериала Kopps управляется с преступниками , то ты не зря зашёл.
Немного о коде и примерах
Я использую archlinux, поэтому все примеры будут в разрезе archlinux. Но на других линукса все действия производятся похожим образом.
Все примеры я старался оформить в виде скриптов, чтобы потом можно было развернуть на новой системе. Буду оставлять ссылки на github.
Шаг 1: Установка XMonad
Данное действие специфичено для archlinux
Первое, что нужно сделать — это поставить yaourt, если он не стоит конечно же. Не буду утомлять, я делаю это скриптом install-01-yaourt.sh. (Когда нашел на просторах интернета, спасибо автору.)
Ставим XMonad:
yaourt -S xmonad xmonad-contrib xmobar dmenu2
Или, если хотим поставить из haskell-core репозитория:
yaourt -S haskell-xmonad haskell-xmonad-contrib xmobar dmenu2
Так же можно поставить через yaourt darcs версию, но этот вирант мы опустим.
Шаг 2: Минимальная настройка XMonad
Конфигурирование XMonad производится с помощью файла ~/.xmonad/xmonad.hs. Как вы уже наверно догадались, конфигурация пишется на Haskell.
Если вы не знаете Haskell, это не беда, польюзуйтесь чужими конфигами. Когда конфиг работает, понять что к чему можно и на понятийном уровне.
Минимальный .xmonad/xmonad.hs:
import XMonad
main = xmonad defaultConfig
{ modMask = mod4Mask -- Use Super instead of Alt
, terminal = "urxvt"
}
Курс молодого бойца по управлению XMonad
При использовании тайлового оконного менеджера, окон как таковых — нет. Есть тайлы. Тайлы ведут себя в соответсвии с текущем Layout автоматически располагаясь так или иначе (например, Layout Grid — тупо отображает таблицой или же Full — отобразить одно главное окно).
Layout
Компанует тайлы. По умолчанию переключение между Layout`s производится с помощью сочетания modKey+space.
В нашем случае modKey = клавише Windows(Super).
Тайл
Это и есть те самые, привычные нам окошки.
В Layout может быть настроена поддержка изменения размера тайлов и количества мастер окон. Так же можно «отсоединить» тайл, зажав кнопку modKey и потянув за окно мышкой. А modKey+RightMouseButton будет изменять размер окошка. Перевести тайл из режима doFloat в стандартный можно комбинацией modKey+t.
Мастер тайл — тайл, или группа тайлов, которые будут отображаться на «самом видном месте». На скришоте в шапке, master тайл самый большой, его сразу видно.
Между тайлами можно переключаться сочетаниями modKey+tab или modKey+j/modKey+k — фокус на предыдущий/следующий тайл. Так же тайлы можно менять местами с мастер тайлом или предыдущими: modKey+entеr — поменять местами текущий тайл и мастер тайл. modKey+J/modKey+K — поменять местами со следующим/предыдущим
Workspace
Это по сути, рабочие столы, для каждого workspace Layout свой и сохраняется при переключении на другие рабочие столы по возвращению. Хотя это поведение можно изменить, но это уже другая история.
Переключаться между Wokspace можно с помощью сочетания modKey+#, где # — номер рабочего стола (не на цифровой клавиатуре).
Подведём итог:
modKey+tab — фокус на следующий (с шифтом на следующий);
modKey+j/modKey+k — фокус на следующий/предыдущий;
modKey+J/modKey+K — поменять текущий и следующий/предыдущий;
modKey+entеr — поменять текущий тайл и мастер тайл местами;
modKey+m — фокус на мастер тайл;
modKey+# — рабочий стол №#;
modKey+t — перевести тайл из режима doFloat в стандартный.
Оставлю это тут: xmonad cheatsheet
Шаг 3: Запуск
Есть много способов запустить XMonad, рассмотрим парочку.
1. Чистый запуск
У нас установлены только XMonad, нам не нужен ни Gnome, ни KDE, ни XFCE. Мы сами по себе.
В этом случае для запуска достаточно сконфигурировать запуск xmonad в файле инициализации X системы: .xinitrc:
setxkbmap -layout "us,ru"
setxkbmap -option "grp:caps_toggle,grp_led:scroll"
xsetroot -cursor_name left_ptr &
export PATH=~/bin:$PATH
#exec startxfce4
#exec startkde
#exec gnome-session
exec dbus-launch xmonad
Полезняшка: мой .xinitrc
Теперь при запуске startx запустется xmonad (конечно же, эта команда исполняется, когда ещё нет X сессии).
2. Замена текущего оконного менеджера
XMonad умеет нагло заменять текущий window manager. Для этого достаточно выполнить простую команду:
xmonad --replace
3. Интеграция с __ПодставитьЧтоНужно__
А подставить можно, например, GNOME (дока для archlinux).
Тут, я думаю, каждый найдёт то, что ему нужно, мы же двинемся к самому интересному.
Шаг 4: Нескучные обои
Если вы запустили xmonad с минимальным конфигом, то уже, наверно, заметили, что там чёрный экран. Обоев нет!
Как же так, подумали мы, в gnome есть, в kde есть… И тут сделаем!
Быстро исправляем это недоразумение:
sudo pacman -S feh
feh --bg-center /usr/share/backgrounds/gnome/Bokeh_Tails.jpg # Тут можно подставить путь до любой картинки. Или, о господи, даже http урл!
feh --bg-center http://habrastorage.org/files/c1a/90a/763/c1a90a763acc48a083a325d42f86f8ad.jpg # да да, даже так!
Вам, наверно, понравилось, да? Можно поставить любимую картинку из интернета прямо на рабочий стол, зафиксируем результат:
echo "feh --bg-center http://habrastorage.org/files/c1a/90a/763/c1a90a763acc48a083a325d42f86f8ad.jpg &">>~/.xinitrc
Шаг 5: Рашпиль
Ну вот теперь можно работать, возьмём в руки инструмент и начнём допиливать XMonad.
Тут можно было бы приложить конфиг и сказать — готово, но нет. Мы же сдесь чтобы хоть чуть чуть разобраться.
Поработаем над нашим конфигом, преобразуем его к следующему виду:
defaults = defaultConfig {
terminal = "urxvt"
, workspaces = myWorkspaces
, modMask = mod4Mask
, borderWidth = 2
}
myWorkspaces :: [String]
myWorkspaces = ["1:web","2:dev","3:term","4:vm","5:media"] ++ map show [6..9]
main = do
xmonad defaults
Теперь наши рабочие столы с названиями, но ты, дядя Фёдор, этого всё равно не увидишь, ведь у тебя xmobar не настроен!
Ладно, отложим xmobar, сделаем нечто более существенное:
defaults = defaultConfig {
terminal = "urxvt"
, workspaces = myWorkspaces
, modMask = mod4Mask
, layoutHook = myLayoutHook
, handleEventHook = fullscreenEventHook -- для корректного отображения окон в полно экранном режиме
, startupHook = setWMName "LG3D" -- для совместимости определёных приложений, java например(IntelliJ IDEA)
, borderWidth = 2
, normalBorderColor = "black"
, focusedBorderColor = "orange"
}
myWorkspaces :: [String]
myWorkspaces = ["1:web","2:dev","3:term","4:vm","5:media"] ++ map show [6..9]
myLayoutHook = spacing 6 $ gaps [(U,15)] $ toggleLayouts (noBorders Full) $
smartBorders $ Mirror tiled ||| mosaic 2 [3,2] ||| tabbed shrinkText myTabConfig
where
tiled = Tall nmaster delta ratio
nmaster = 1
delta = 3/100
ratio = 3/5
main = do
xmonad defaults
Теперь посмотрим что получилось, для этого:
- перекомпилим командой xmonad --recompile
- если нет ошибок перезапустим xmonad --restart
И, вуаля, изменения должны вступить в силу.
Выполним комбинацию modKey+shift+enter. Должнен открыться тайл с консолью. Если не открылся, возможно, проблема в строчке конфига xmonad.hs:
terminal = "urxvt"
Укажите терминал, которые есть в системе, или установите urxvt:
sudo pacman -S rxvt-unicode
Сочетанием modKey+p можно вызвать dmenu (откроется сверху, набирая команду, там будет отобажён список приложений, которые можно запустить). Вызовем gvim, например, modKey+p -> печатаем gvim (если он, конечно, есть в системе) жмакаем enter.
Итак, у нас есть рабочие столы, тайлы, лайауты… Так давайте же автоматически направлять приложения на разные рабочие столы? Давайте.
Идём в наш конфиг xmonad.hs и добавляем следующее:
...
defaults = defaultConfig {
terminal = "urxvt"
, workspaces = myWorkspaces
, modMask = mod4Mask
, layoutHook = myLayoutHook
, handleEventHook = fullscreenEventHook -- для корректного отображения окон в полно экранном режиме
, startupHook = setWMName "LG3D" -- для совместимости определёных приложений, java например(IntelliJ IDEA)
, borderWidth = 2
, manageHook = myManageHook -- Добавили ХУК Сюда
, normalBorderColor = "black"
, focusedBorderColor = "orange"
}
-- Добавим хуук с реализацией
myManageHook :: ManageHook
myManageHook = composeAll . concat $
[ [className =? c --> doF (W.shift "1:web") | c <- myWeb]
, [className =? c --> doF (W.shift "2:dev") | c <- myDev]
, [className =? c --> doF (W.shift "3:term") | c <- myTerm]
, [className =? c --> doF (W.shift "4:vm") | c <- myVMs]
, [manageDocks]
]
where
myWeb = ["Firefox","Chromium","Chrome"]
myDev = ["Eclipse","Gedit","sublime-text"]
myTerm = ["Terminator","xterm","urxvt"]
myVMs = ["VirtualBox"]
....
Теперь
xmonad --recompile && xmonad --restart
Через dmenu запускаем например sublime-text, и вот она! Вот она магия! Он сразу оказался на рабочем столе с пометкой 2:dev.
Нажмём modKey+shift+enter для запуска терминала и, о чудо! Он окажется на 3-м рабочем столе.
А как же мне узнать className тайла для отправки на нужный рабочий стол?
Это очень просто. Открываем консоль, набираем команду xprop, дальше тыркаем мышкой в нужное окно и в консоле отобразится информация о нём. Нас интересует поле WM_CLASS(STRING).
Впринципе, не обязательно именно по className фильтровать окна, можно и по другим параметрам. Можно увидеть, что, например, по полю title так же можно отправить окошко куда душе угодно.
Это то, к чему мы так долго шли…
И тут мы вспомнили о дяде Фёдоре. Точнее — о xmobar. Давайте сделаем статус бар. Для тех, кто ещё не понял, это чёрная панелька сверху (скриншот в шапке).
Шаг 6: Напильник
Итак, xmobar уже должен быть установлен. Поэтому открываем наш конфиг xmonad.hs и меняем:
main = do
xmonad defaults
На:
main = do
xmproc <- spawnPipe "/usr/bin/xmobar ~/.xmonad/xmobar.hs"
xmonad $ defaults {
logHook = dynamicLogWithPP $ defaultPP {
ppOutput = System.IO.hPutStrLn xmproc
, ppTitle = xmobarColor xmobarTitleColor "" . shorten 100
, ppCurrent = xmobarColor xmobarCurrentWorkspaceColor "" . wrap "[" "]"
, ppSep = " "
, ppWsSep = " "
, ppLayout = ( x -> case x of
"Spacing 6 Mosaic" -> "[:]"
"Spacing 6 Mirror Tall" -> "[M]"
"Spacing 6 Hinted Tabbed Simplest" -> "[T]"
"Spacing 6 Full" -> "[ ]"
_ -> x )
, ppHiddenNoWindows = showNamedWorkspaces
}
} where showNamedWorkspaces wsId = if any (`elem` wsId) ['a'..'z']
then pad wsId
else ""
Нет времени ничего объяснять, просто создаём дальше конфиги, а именно ~./xmonad/xmobar.hs:
Config {
font = "xft:Droid Sans Mono:size=9:bold:antialias=true"
bgColor = "#000000",
fgColor = "#ffffff",
position = Static { xpos = 0, ypos = 0, width = 1920, height = 16 },
lowerOnStart = True,
commands = [
Run Weather "UUDD" ["-t","<tempC>°C","-L","18","-H","25","--normal","green","--high","red","--low","lightblue"] 36000
,Run Memory ["-t","<used>/<total>M (<cache>M)","-H","8192","-L","4096","-h","#FFB6B0","-l","#CEFFAC","-n","#FFFFCC"] 10
,Run Network "enp6s0" [
"-t" ,"rx:<rx>, tx:<tx>"
,"-H" ,"200"
,"-L" ,"10"
,"-h" ,"#FFB6B0"
,"-l" ,"#CEFFAC"
,"-n" ,"#FFFFCC"
, "-c" , " "
, "-w" , "2"
] 10
,Run Date "%Y.%m.%d %H:%M:%S" "date" 10
,Run MultiCpu [ "--template" , "<autototal>"
, "--Low" , "50" -- units: %
, "--High" , "85" -- units: %
, "--low" , "gray"
, "--normal" , "darkorange"
, "--high" , "darkred"
, "-c" , " "
, "-w" , "3"
] 10
,Run CoreTemp [ "--template" , "<core0> <core1> <core2> <core3> <core4>°C"
, "--Low" , "70" -- units: °C
, "--High" , "80" -- units: °C
, "--low" , "darkgreen"
, "--normal" , "darkorange"
, "--high" , "darkred"
] 50
,Run StdinReader
],
sepChar = "%",
alignSep = "}{",
template = "%StdinReader% }{ %coretemp% | %multicpu% | %memory% | %enp6s0% | %UUDD% | <fc=#FFFFCC>%date%</fc> "
}
Ух, теперь можно присесть и выполнить уже знакомую команду:
xmonad --recompile && xmonad --restart
Должен был появится наш долгожданный бар и теперь, %USERNAME%, должен наконец увидеть, на каком он рабочем сталое находится. Так же вынесли заголовок текущего окна в наш бар (прям как в mac os x, только гибче). За это отвечает dynamicLogWithPP, который копирует информацию в stdin xmobar, предварительно форматируя её.
Очень подробно о xmobar и его плагинах тут.
Будьте внимательны, в font нужно указать существущий шрифт в вашей системе. Его можно найти в выводе команды fc-list.
Шаг 7: Надфиль
Вроде всё работает, но как-то не уютно. Чего бы ещё такого сделать? Давайте отобразим Volume Level в нашем баре! Хм, ХМобаре! Сказал — делай.
Изменяем ~/.xmonad/xmobar.hs
Добрые люди уже написали для нас плагин PipeReader, который тупо вычитывает pipe и отображает это дело в баре.
Добавим вызов плагина PipeReader и изменим шаблон добавив в него отображение громкости:
,Run PipeReader "/tmp/.volume-pipe" "vol"
template = "%StdinReader% }{ %vol% | %coretemp% | %multicpu% | %memory% | %enp6s0% | %UUDD% | <fc=#FFFFCC>%date%</fc> "
Создадим pipe
export _volume_pipe=/tmp/.volume-pipe
[[ -S $_volume_pipe ]] || mkfifo $_volume_pipe
Теперь у нас есть pipe, сливаем в него нужные данные. Попробуем узнать уровень громкости следующей командой:
amixer sget Master | grep -o -m 1 '[[:digit:]]*%' | tr -d '%'<source>
Отлично, вот его и "сольём":
<source lang="bash">echo `amixer sget Master | grep -o -m 1 '[[:digit:]]*%' | tr -d '%'`>/tmp/.volume-pipe<source>
Обновленные данные отобразились в xmobar.. Вё равно как то счастья не видно. Может дело в этих сухих цифрах? Так давайте сделаем бар громкости в xmobar! Ух, повеселело сразу.
Создаем скрипт ./xmonad/getvolume.sh:
<source lang="bash">#!/bin/sh
vol=`amixer sget Master | grep -o -m 1 '[[:digit:]]*%' | tr -d '%'`
level=`expr $vol / 10`
bars=$level
case $bars in
0) bar='[----------]' ;;
1) bar='[|---------]' ;;
2) bar='[||--------]' ;;
3) bar='[|||-------]' ;;
4) bar='[||||------]' ;;
5) bar='[|||||-----]' ;;
6) bar='[||||||----]' ;;
7) bar='[|||||||---]' ;;
8) bar='[||||||||--]' ;;
9) bar='[|||||||||-]' ;;
10) bar='[||||||||||]' ;;
*) bar='[----!!----]' ;;
esac
echo $bar
exit 0
Примерно так, зато быстро. Проверяем:
echo `~/.xmonad/getvolume.sh`>/tmp/.volume-pipe
Не знаю как у вас, а у меня работает. Но как то оно… не автоматически. Хочется ещё вкусняшек, а если хочется, зачем останавливаться?
Бонусные вкусняшки
Редактируем наш ~/.xmonad/xmonad.hs.
Добавим следующее:
defaults = defaultConfig {
...
}`additionalKeys` myKeys -- добавили к дефолтной конфигурации новые кнпоки!
myKeys = [
((mod4Mask, xK_g), goToSelected defaultGSConfig)
, ((mod4Mask, xK_s), spawnSelected defaultGSConfig ["chromium","idea","gvim"])
, ((mod4Mask, xK_KP_Add), spawn "amixer set Master 10%+ && ~/.xmonad/getvolume.sh >> /tmp/.volume-pipe")
, ((mod4Mask, xK_KP_Subtract), spawn "amixer set Master 10%- && ~/.xmonad/getvolume.sh >> /tmp/.volume-pipe")
]
Теперь при нажатии на modKey+ -/+ (это — и + на NumKeyboard) будет изменяться громкость и её уровень сразу отобразится в нашей панельке.
Ещё не уснувший читатель мог заметить дополнительную вкусняшку в виде строчки:
((mod4Mask, xK_s), spawnSelected defaultGSConfig ["chromium","idea","gvim"])
В качестве вознаграждения он может исполнить хитрую комбинацию клавиш и увидеть результат.
Заключение
Хочу лишь сказать, что я не претендую на какую либо исключительность этого материала. Да и правильным его не назовешь, наверняка всё можно сделать лучше. Я всего лишь хотел показать путь, по которому можно пойти для настройки собственного окружения так, чтобы этой холодной осенью на душе было тепло и приятно.
Надеюсь, было интересно и полезно, с радостью обсужу тематику рабочего окружения, xmonad и всего, что связанно с Linux.
PS: Для экономии места все примеры конфигов не снабжены необходимыми директивами import. Импорты можно стянуть с гитхаба.
Материалы
Сайт XMonad — много инфы и доки по API;
Xmobar Reference — дока по Xmobar и его плагинам;
Архив конфигураций XMonad — примеры кофнигов с прилагающимися картинками результата;
XMonad hotkey cheatsheet — все хоткеи на одной страничке. Для начала советую feh --bg-center www.haskell.org/wikiupload/b/b8/Xmbindings.png;
GitHub xmonad-config — Все конфиги, которые тут использовал, в кучку собрал да на гитхабе разместил.
Автор: tolkkv