Страницы

понедельник, 12 ноября 2012 г.

Haskell и XMonad в Ubuntu

Установка Haskell и XMonad в Ubuntu 12.10 Quntal Quetzal

Я заметил, что последнее время, с переходом на Gnome Shell, всё чаще использую полноэкранные режимы приложений на нескольких рабочих столах.
Стало несколько неудобно, каждый раз запускать и перемещать несколько приложений по различным столам, после перезагрузки.
Легкого решения для Gnome Shell не нашлось. А всего лишь надо, автозагрузка, авторасположение по рабочим столам, удобное расположение на столе и чтобы после перезагрузки ничего не менялось.

И вот, я докатился до Xmonad.


Фреймовый оконный менеджер Xmonad написан на языке Haskell и на нём же настраивается (буквально в файле ~/.xmonad/xmonad.hs).
Что может быть получено на экране с Xmonad [см. Ресурсы п.8]



Т.к. без обзорного знания языка Haskell не обойтись, то установим и сам язык Haskell, точнее его платформу Glasgow Haskell Platform [см. Ресурсы п.1].


Установка версии языка из репозитория Ubuntu:

$ sudo apt-get install haskell-platform haskell-platform-doc haskell-platform-prof

Установка версии xmonad из репозитория Ubuntu:

$ sudo apt-get install xmonad
После установки надо выйти из системы и войти, но уже со съянсом xmonad.
Появиться просто рабочий стол, без всего. Чтобы запустить bash окно, надо нажать Alt+Shift+Enter.



Запуск интерактивной среды языка Haskell:
$ ghci

Я, было в начале набрал haskell.:-)

Версия платформы:
$ ghci --version
The Glorious Glasgow Haskell Compilation System, version 7.4.2

Приглашение к вводу языковых конструкций и команд.
Prelude>



Prelude - это стандартная библиотека, загруженная по умолчанию, в каждой haskell-программе.

:quit - покинуть это "мутное" место
:help - справка по командам. "продолжить мутить"

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

Prelude> cos pi
Prelude> 2 ^ 2
Prelude> sqrt 4


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

Современные языки - модульные, поэтому библиотека Haskell разбита на модули и иерархична.
В Haskell есть репозиторий "open-source" программ - Hackage.

Haskell - мощный язык, поэтому можно использовать в нём знакомый императивный стиль написания программ и более правильный - функциональный, а можно смешивать. Понятно, что по-началу пойдет императивный стиль, ведь достаточно сложно мыслить в функциональном стиле.


XMonad



Главный конфигурационный файл: ~/.xmonad/xmonad.hs

Синтаксис конфигурационного файла: язык Haskell.
По умолчанию, отсутствует. Для настройки - надо создать, либо взять готовый [см. Ресурсы п.8, п.12].

Базовые понятия:

Screen - монитор, в многомониторных конфигурациях
Workspace - аналогично Virtual Desktop Workspace, в X Window
Layout - расположение окон отображаемое на конкретном Workspace.
Master pane - главное окно, обычно самое большое в Layout.
Tile pane - остальные окна в Layout.


Минимальное содержимое конфигурационного файла ~/.xmonad/xmonad.hs:

import xmonad

main = do             xmonad $ defaultConfig

В Ubuntu, xmonad устанавливается как дополнительная сессия, так что её можно выбрать в окне входа в систему (GDM, LightDM).

И после появления пустого стола, сразу же создать окно (alt+shuft+enter) или несколько.
И сразу же завершить сессию (alt+shift+q), т.к. подготовиться лучше из привычного окружения.

Кобминации клавиш Xmonad, используемых по-умолчанию, можно найти здесь: http://www.haskell.org/haskellwiki/Image:Xmbindings.png



XMonad - в принципе, это подмножество библиотеки.

Для подключения модуля в файле функций (.hs) используется синтаксис:
import <имя модуля>

import xmonad - подключаем основные функции XMonad.

Далее мы определяем функцию с именем main (без параметров). Символ "=" - определение функции. Имя main - специальное имя - точки входа в программу на языке Hashell.

Тело функции, в данном определении, начинается со слова do - ключевое слово языка, объединяющего вызовы функций в порядок исполнения.

В Haskell используется отбивка (т.н. двумерный синтаксис, как в языке python), поэтому строка xmonad $ defaultConfig располагается после табуляции, т.е. отступы помогаю анализатору определить границы определений.

xmonad - это, понятно, вызов функции.
defaultConfig - это что-то большое, емкое, там есть что посмотреть - настроить. Т.к. Haskell функциональный язык, предположим, что это функция, переданная в качестве параметра. Из названия понятно, что это конфигурация по умолчанию. Больше ничего не понятно.:-)
$ - оператор нестрогого применения - это уже из учебника. Можно временно рассматривать как разделитель вызовов функций.

Далее, надо узнать что ещё есть внутри модуля xmonad, для этого посмотрим документацию [см. Ресурсы].
Откуда становиться понятно, что defaultConfig - это структура данных, с типом XConfig. Что нивелирует первоначальное предположение. А просмотр XConfig показывает т.н. конструкторы, которые можно использовать для конструирования уже нашей структуры данных, с нашими значениями, которые настроят нам Xmonad.

Вызовы конструкторов оформляются следующим образом:
{
имя конструктора = значения конструктора
}

Приведу некоторые из конструкторов здесь:
workspaces - как ясно из названия, конструктор задающий "виртуальные столы". Тип - список. Список имен виртуальных столов, в виде пар номер:название
keys - привязка клавиш к действиям.
mouseBindings - привязка кнопок мыши к действиям. Выражено как тип "map".

Есть несколько конструкторов, со словом hook в  названии и параметром в виде функции. Обычно они используются для вызова пользовательских функций, переопределенных в конфигурационном файле.

startupHook - выполняется при загрузке. Автозапуск.

manageHook - выполняется при создании (открытии) нового окна.
layoutHook - задает расположение окон тип Window.

terminal - указывается терминальная программа. Тип - строка.

Несколько конструкторов, относящихся к рамках окон.

normalBorderColor - цвет рамки обычного окна
focusedBorderColor - цвет рамки окна с фокусом ввода.

borderWidth - ширина рамки окон, Тип. Dimension


Теперь, самое время отвлечься и продумать структуру "виртуальных столов". Опыт уже имеется, при настройке tmux, так что это быстро.
Общий стол - для обычных задач, 3 или 4 окна, одно центральное, большое, одно с суперпользователем.
Интернет - 1 окно браузера, по возможности на весь экран.
Почта и связь - 2 -3  окна, почтовая программа, мессенджер.
Сервер - 1 окно. Сессия ssh к микросерверу.
Сеть - несколько окон, мониторинг домашней сети.
База - 1 окно с tmux, или несколько, с сессиями к базе данных PostgreSQL.
Просмотр - просмотр файлов на полный экран, либо 2 окна.
Фото - фотоальбом.
Видео - видеопросмотр.

9 - столов, 9 клавиш (mod+цифра).

Xmonad поддерживает многомониторные конфигурации,  с помощью средства Xinerama оконной системы X Window.

1 физический монитор (screen) - несколько рабочих столов (workspaces)
1 рабочий стол - несколько расположений (раскладок, layouts)
1 расположение - несколько окон

Т.е. при серьезной настройке можно получить "центр управления полетами в сети".

В принципе, раскладку окон можно задать и  в обычном файле xinitrc чистого X Window, если нужно постоянное неизменяемое расположение, раз и навсегда. Xmonad просто делает процесс попроще, чем опция --geometry.

Т.к. Haskell современный язык, то поддержка UTF-8 встроена по-умолчанию, а это, даёт нам некоторые приятные возможности, по повышению понимания конфигурации.



Например, зададим список рабочих столов на языке Haskell: (выдержка из моего xmonad.hs)


 стол_общий     = "1:Общий"     -- Общий рабочий стол
 общий_стол     = стол_общий    -- в другой языковой форме
 стол_интернет  = "2:Интернет"  -- Просмотр Интернета
 стол_почты     = "3:почта"     -- Почтовое и разговорное
 стол_сервер    = "4:Микросервер"  -- Доступ к серверу
 стол_сеть      = "5:Сеть"      -- Домашняя сеть
 стол_база      = "6:База"      -- База данных, разработка
 стол_просмотра = "7:Просмотр"  -- Справочные материалы
 стол_фото      = "8:Фото"      -- Фото
 стол_разное    = "9:разное"    -- Разговоры, файловый менеджер

 рабочие_столы  = [стол_общий,
                  стол_интернет,
                  стол_почты,
                  стол_сервер,
                  стол_сеть,
                  стол_база,
                  стол_просмотра,
                  стол_фото,
                  стол_разное
                 ]

Приятно то, что это легитимные определения в языке Haskell. Я не удержался, написал на русском языке почти всё, до чего дотянулся. Кстати, это действительно, резко повысило скорость восприятия конфигурации и скорость переконфигурирования, в моём случае.


Layout. Расположения. Расположение окон

Расположение (Layout).
В Xmonad стандартно поставляются 3 расположения.
Tall разделение по вертикали на главную и вспомогательную части
Mirror Tall - раделение по горизонтали на главную и вспомогательную части. Mirror - это модификатор.
Full -полноэкранное расположение, переключение между окнами mod+tab

Принцип, по которому устроены расположения, декораторы - это наслаивание (модифицирование), задается в виде: Модфикатор $ расположение. Например, Mirror - это модификатор, Tall - расположение,
master delta ratio - это параметры расположения Tall.
Еще пример, простой модификатор "spacing 5", модифицирует расположение, добавляя 5 пиксельный разрыв между окнами. Для него не важно какое расположение.
onWorkspace - это из модуля PerWorkspace (по столам) - позволяет задать для каждого стола свое расположение окон.
||| - оператор "выбора", насколько я понял.

 расположение =
   onWorkspace стол_разное ( общее_расположение ||| сеточное_расположение ) $
   onWorkspace общий_стол общее_расположение $
   onWorkspace стол_просмотра общее_расположение $
   onWorkspace стол_фото расположение_для_gimp $
   onWorkspaces [стол_интернет, стол_сервер] расположение_на_весь_экран $
   общее_расположение ||| общее_горизонтальное_расположение ||| расположение_на_весь_экран $
  where
   общее_расположение = spacing 5 $ Tall master delta ratio
   общее_горизонтальное_расположение = spacing 5 $ Mirror $ Tall master delta ratio
   defaultTall = ResizableTall 1 (3/100) (1/2) []
   master = 1
   ratio = 2/3
   delta = 3/100
   расположение_на_весь_экран = smartBorders $ Full
   сеточное_расположение = spacing 6 $ Grid
   расположение_для_gimp = simpleDeco shrinkText цветовое_оформление $ defaultTall


Здесь важное слово "where", которое позволяет определить функции и значения, после упоминания, что повышает восприимчивость синтаксиса.
Т.е. в этом блоке определения, я задаю конкретные расположения окон (layouts),  а выше, раскладываю их по рабочим столам.

Полноэкранное расположение Full

При полноэкранном расположении, каждое окно, занимает весь экран. Невозможно сдвинуть, изменить, скрыть. Зато возможно переключаться окнами в полноэкранном режиме, с помощью клавиатурных сочетаний mod + tab, где mod - по умолчанию alt, а у меня win.


Собственные привязки клавиш

Привязка определенной клавиши задается в виде пары - клавиша-действие. Затем все привязки помещаются в список и список передается в функцию.

На мультимедийной клавиатуре, часто присутствуют клавиши управлению громкостью звука, имена кодов XSymbols для этих кнопок, в Haskell определены так:

xF86XK_AudioLowerVolume
xF86XK_AudioRaiseVolume

xF86XK_AudioMute

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

 мультимедийные_клавиши = [
          ((0, xF86XK_AudioLowerVolume), kill)          -- уменьшает громкость
        , ((0, xF86XK_AudioRaiseVolume), kill)          -- увеличивает громкость
        , ((0, xF86XK_AudioMute), kill)                 -- выключает звук
        ]

Здесь, они временно выполняют функцию "kill" - закрыть окно. Т.к. с управлением звуком из XMonad я еще не определился. В Gnome присутствует PulseAudio, а это надо RTFM.

Потом, просто соединим этот список клавиш и основной. Т.е. мы логически сгруппируем привязку клавиш, для удобства просмотра и изменения.


Часто встречаются клавиши:

xF86XK_HomePage
xF86XK_Mail
xF86XK_Files
xF86XK_Favorites

По аналогии, также сформируем список дополнительных клавиш, присутствующих на клавиатуре.

  клавиши_запуска = [
          ((0, xF86XK_Close), kill)                     -- Закрыть окно
        , ((0, xF86XK_HomePage), spawn "firefox http://gimmor.blogspot.com/")
        , ((0, xF86XK_Mail), spawn "evolution")         -- Почта
        , ((0, xF86XK_Calculator), spawn "gcalctool")   -- Калькулятор
        , ((0, xF86XK_LogOff), spawn "gcalctool")       -- Выйти из съянса

        , ((0, xF86XK_Sleep), spawn "gcalctool")        -- Спящий режим
        , ((0, xF86XK_Launch1), spawn "gcalctool")      -- Проверка
        , ((0, xF86XK_Favorites), spawn "nautilus")     -- Файлы
        , ((0, xF86XK_Messenger), spawn "skype")        -- Разговоры
        ]

spawn - это команда запуска внешнего приложения
gcaltool - калькулятор, для клавиш, которые ещё не настроены.


Поработаем над секцией import

import Graphics.X11.ExtraTypes.XF86 - содержит определения клавиш,таких как мультимедия клавиши.
Полные определения можно найти в файлах: Graphics/X11/Types.hsc и Graphics.X11.ExtraTypes.hsc.

import XMonad.Layout.Spacing - позволяет раздвинуть окна, для лучшего визуального выделения.

import XMonad.Layout.NoBorders(smartBorders) - позволяет показывать окна без рамок

import XMonad.Layout.PerWorkspace - позволяет задавать конфигурацию для каждого рабочего стола

Секция простая, приводить не буду здесь, полное её содержание можно посмотреть ниже, в полном файле конфигурации.


ManageHook. Заглушки поведения

Заглушки поведения, это "подпрограммы", которые вызываются менеджером Xmonad, при создании нового окна. Новое окно, в X Window имеет некоторые свойства, на основе которых Xmonad может принимать решения, относительно того, что делать с этим окном. Будь то, переместить на другой рабочий стол, разместить по центру и многое другое.

Значимые свойства окна в X Window, пример:

WM_CLASS: className =? "Firefox"
WM_TITLE: title =? "Firefox"
WM_NAME: appName =? "firefox"
WM_ROLE: (getStringProperty "WM_ROLE") =? "Roster window"

Вот выдержка того, как я задаю поведение:

 поведение_программ = composeAll
      [ поведение_браузеров
      , поведение_просмотрщиков
      , поведение_почтовых
      , для_калькулятора
      , для_скайпа
      , для_файлового_менеджера
      , для_менеджера_фотографий
      , для_minitube
      , для_gimp
      , className =? "File Operation Progress" --> разместить_по_центру_стола
      , поведение_диалоговых_окон
      ]

Здесь я также, разложил на маленькие кусочки кода, для лучшего понимания. Чуть ниже идут определения, уже конкретные:

        isDialog --> разместить_по_центру_стола

 поведение_браузеров =
        className =? "Firefox"
        --> doShift стол_интернет

В этих определениях, уже вызываются функции специфичные для Xmonad, выполняющие определенные действия (например, doShift - переместить на указанный стол). Здесь решение выполняется на основе класса окна (className).

Конфигурация и её вызов

Полная конфигурация, задается на основе встроенной конфигурации по-умолчанию, путем модификации вызовов функций, посредством конструкторов.
Здесь я меняю клавишу mod, с alt, на win. Указываю свой список рабочих столов, добавляю свои привязки клавиш и мыши, указываю заглушки поведения и свои расположения.

 рабочая_конфигурация = defaultConfig
     { manageHook = manageDocks
        <+> поведение_программ
                 <+> manageHook defaultConfig
     , layoutHook = avoidStruts $ расположение
     , terminal = "gnome-terminal --hide-menubar"
     , modMask = mod4Mask  -- меняем привязку клавиши, вместо alt будет  win
     , workspaces = рабочие_столы
     , normalBorderColor = цвет_рамки_обычного_окна
     , focusedBorderColor = цвет_рамки_выделенного_окна
     , borderWidth = 4
     , startupHook = return ()
     }  `additionalKeys` все_клавиши
        `removeKeys` удаляемые_клавиши
    -- `additionalMouseBindings` клавиши_мыши


Вызов конфигурации происходит в главной фукнции main так:

 main = do
   xmonad $ рабочая_конфигурация


Т.е. прослеживается путь от точки входа, к каждой секции конфигурации.


Общая сборка конфигурационного файла Xmonad


Приведу файл настроек Xmonad, таким, как он находится на текущий момент конфигурации. Пошёл 3 день общения. Пока не подключен xmobar.



После копирования файла в папку .xmonad/ запустить компиляцию:

$ xmonad --recompile

Файл у меня компилируется нормально, проблемы очень часто возникают из-за отступов и из-за пропуска подчеркивания в русских именах. :-)

$ cat $HOME/.xmonad/xmonad.hs

 -- Конфигурация xmonad для рабочего стола X Window
 -- сервер: mir
 -- Система: Ubuntu 12.10 Gnome Shell,X Window, xmonad, xmobar
 -- Дата основания: 10.11.2012
 -- Описание в web: http://gimmor.blogspot.com/label/xmonad
 -- Ключевые слова: xmonad, xmonad.hs

 -- Содержание
 --
 --    I. Секция импорта библиотек
 --   II. Секция имен рабочих виртуальных столов (пространств)
 --  III. Секция расположений для рабочих виртуальных столов
 --   IV. Секция заглушек поведения специфических приложений
 --    V. Секция офрмления (цвета, шрифты)
 --   VI. Секция привязки клавиш
 --  VII. Секция привязки мыши
 -- VIII. Секция автозагрузки внешних программ
 --   IX. Секция конфигураций
 --    X. Секция главной функции main - точка входа
 --     . Дополнительная информация
 --     . Ресурсы


 ----------------------------------------------------------------------------------------
 --    I. Секция импорта библиотек (подключение пространств иимен)
 ----------------------------------------------------------------------------------------

 import XMonad
 import XMonad.Hooks.DynamicLog 
 import XMonad.Hooks.ManageDocks        -- Управляет выделением места на экране
 import XMonad.Hooks.ManageHelpers        -- Вспомогательные функции размещения
 import XMonad.Util.Run (spawnPipe)          -- Утилита для запуска внешних программ
 import XMonad.Util.EZConfig 
 import Graphics.X11.ExtraTypes.XF86          -- Определения мультимедийных клавиш в X

 import XMonad.Layout.Spacing              -- Визуальные разрывы между окнами
 import XMonad.Layout.NoBorders(smartBorders)   -- Окна без рамок
 import XMonad.Layout.PerWorkspace          -- Разные расположения для столов
 import XMonad.Layout.ResizableTile        -- изменение размеров
 import XMonad.Layout.IM              -- Расположение для мессенджеров
 import XMonad.Layout.Grid            -- Расположение - сетка окон 
 import XMonad.Layout.SimpleDecoration        -- Простой декор вокруг окна
 import XMonad.Layout.BorderResize

 --import XMonad.Actions.GridSelect
 import Data.Ratio ((%)) 
 import XMonad.Actions.CycleWS            -- Циклическое переключение столов 
 import qualified XMonad.StackSet as W 
 import System.IO 
 import XMonad.Util.Font

 ----------------------------------------------------------------------------------------
 --   II.  Секция задания имен рабочих виртуальных столов (всего 9)
 ----------------------------------------------------------------------------------------

 стол_общий     = "1:Общий"       -- Общий рабочий стол
 общий_стол    = стол_общий    -- ссылка, в другой языковой форме
 стол_интернет  = "2:Интернет"     -- Просмотр Интернета
 стол_почты     = "3:почта"        -- Почтовое и разговорное
 стол_сервер    = "4:Микросервер"  -- Доступ к серверу
 стол_сеть      = "5:Сеть"      -- Домашняя сеть
 стол_база      = "6:База"         -- База данных, разработка
 стол_просмотра = "7:Просмотр"     -- Справочные материалы
 стол_фото      = "8:Фото"        -- Фото
 стол_разное    = "9:разное"       -- Разговоры, файловый менеджер

 рабочие_столы  = [стол_общий,
          стол_интернет,
          стол_почты,
          стол_сервер,
          стол_сеть,
          стол_база,
          стол_просмотра,
          стол_фото,
          стол_разное
         ]


 ----------------------------------------------------------------------------------------
 --  III. Секция расположений окон, в том числе на различных столах
 ----------------------------------------------------------------------------------------
 -- Стандартные расположения
 -- Tall разделение по вертикали на главную и вспомогательную части
 -- Mirror Tall - раделение по горизонтали на главную и вспомогательную части
 -- Full -полноэкранное расположение, переключение между окнами mod+tab

 -- Для каждого монитора, в мултимониторной конфигурации (Xinerama) может быть
 -- несколько рабочих столов
 -- Для каждого стола может быть несколько расположений (one-to-many,1-N)
 -- перечисление (выбор) задается оператором |||, а расположения помещаются в скобки

 -- Сейчас один монитор


 расположение =   
    onWorkspace стол_разное ( общее_расположение ||| сеточное_расположение ) $
    onWorkspace общий_стол общее_расположение $
    onWorkspace стол_просмотра общее_расположение $
    onWorkspace стол_фото расположение_для_gimp $
    onWorkspaces [стол_интернет, стол_сервер] расположение_на_весь_экран $
    общее_расположение ||| общее_горизонтальное_расположение ||| расположение_на_весь_экран
  where
   общее_расположение = spacing 5 $ Tall master delta ratio
   общее_горизонтальное_расположение = spacing 5 $ Mirror $ Tall master delta ratio
   defaultTall = ResizableTall 1 (3/100) (1/2) []
   master = 1
   ratio = 2/3
   delta = 3/100
   расположение_на_весь_экран = smartBorders $ Full 
   сеточное_расположение = spacing 6 $ Grid
   расположение_для_gimp = simpleDeco shrinkText цветовое_оформление $ defaultTall


 ---------------------------------------------------------------------------------------
 --   IV. Секция заглушек для специфической обработки программ, всплывающих окон и пр.
 ----------------------------------------------------------------------------------------

 -- Это то место, где можно настроить  поведение при запуске сложных многооконных программ
 -- Для определения класса окна, надо запустить специальную программу xprop
 --
 -- className =? "Firefox"
 -- title =? "Firefox"
 -- appName =? "Firefox"
 -- (getStringProperty "WM_ROLE") =? "Roster window"

 -- Сложные программы для размещения, это мессенджеры, gimp и т.п.

 поведение_программ = composeAll      
      [ поведение_браузеров
      , поведение_просмотрщиков
      , поведение_почтовых
      , для_калькулятора
      , для_скайпа
      , для_файлового_менеджера
      , для_менеджера_фотографий
      , для_minitube
      , для_gimp
      , className =? "File Operation Progress" --> разместить_по_центру_стола 
      , resource =? "desktop_window" --> doIgnore
      , поведение_диалоговых_окон           
      ]
          where
     положить_на = doShift

 положить_на = doShift
 разместить_по_центру_стола = doCenterFloat

-- Для диалоговых окон - размещение по центру, плавающими
 

 поведение_диалоговых_окон =
    isDialog --> разместить_по_центру_стола

 поведение_браузеров =
    className =? "Firefox"
    --> doShift стол_интернет

 поведение_просмотрщиков =
        className =? "evince"
        --> положить_на стол_просмотра

 поведение_почтовых =
     className =? "Evolution"
     --> положить_на стол_почты

 для_калькулятора =
    appName =? "gcalctool"
    --> разместить_по_центру_стола

 для_скайпа =
    appName =? "skype"
    --> положить_на стол_разное

 для_файлового_менеджера =
    appName =? "nautilus"
    --> положить_на стол_разное
 для_менеджера_фотографий =
    appName =? "shotwell"
    --> положить_на стол_фото
 для_minitube =
        appName =?  "minitube"
        --> положить_на стол_просмотра


 -- Графический редактор GIMP
 -- 2 режима отображения поддерживается: отдельные окна и однооконный
 -- Однооконный режим позволяет использовать Gimp в компоновке полного экрана
 -- Многооконный режим надо настраивать поведение отдельных оконных ролей
 -- главное окно изображения WM_WINDOW_ROLE(STRING) = "gimp-image-window"
 -- панель вкладок WM_WINDOW_ROLE(STRING) = "gimp-dock"
 -- панель инструментов WM_WINDOW_ROLE(STRING) = "gimp-toolbox"
 для_gimp =
    className =? "Gimp"
    --> (положить_на стол_фото)


 ----------------------------------------------------------------------------------------
 --    V. Секция оформления (цвета, шрифты и т.п.)
 ----------------------------------------------------------------------------------------
 -- Определения цветов задаются в 24-битном пространстве RGB

 цвет_рамки_выделенного_окна  = "#68e862"
 цвет_рамки_обычного_окна     = "#60A1AD"

 цветовое_оформление = defaultTheme

    { activeColor         = "orange"    -- цвет активного окна
    , inactiveColor       = "#222222"    -- цвет неактивного окна
    , urgentColor         = "yellow"    -- не знаю
    , activeBorderColor   = "orange"    -- цвет рамки активного окна
    , inactiveBorderColor = "#222222"    -- цвет рамки неактивного окна
    , urgentBorderColor   = "yellow"    -- цвет рамки какого-то окна
    , activeTextColor     = "black"    -- цвет текста активного окна
    , inactiveTextColor   = "#222222"    -- цвет текста неактивного окна
    , urgentTextColor     = "yellow"    -- цвет текста какого-то окна
    , fontName           = "-*-terminus-bold-*-*-*-16-*-*-*-*-*-*-u" -- шрифт
    -- , decoWidth      = 100
    , decoHeight          = 20
    , windowTitleAddons = [("<<<", AlignRight)] -- Заголовок окна и его размещение
    -- , windowTitleIcons    = []
    }

 -- Сформировать строку шрифта можно с помощью программы xfontsel

 ----------------------------------------------------------------------------------------
 --   VI. Секция привязки клавиш
 ----------------------------------------------------------------------------------------

 -- Доступные операции можно найти в XMonad.Operations
 -- http://www.haskell.org/haskellwiki/Xmonad/Key_codes
 -- Константы клавиш можно посмотреть в Graphics/X11/ExtraTypes/XF86.hsc

 -- Используемые клавиши модификаторы (Ctrl,Shift,Alt,Win и т.п.)

 -- shiftMask
 -- сontrolMask
 -- mod1Mask
 -- mod4Mask

 -- Клавиши управления менеджером окон XMonad
 -- Т.к. много мониторов, на каждом много столов, у которых много расположений
 -- то предусмотрим клавиши для циклического переключения
 управляющие_клавиши = [
    ((mod4Mask, xK_space),nextWS)            -- переключает на след. стол
    -- , ((altMask, xK_space), prevWS)        -- переключает на пред. стол
    , ((mod1Mask, xK_space), sendMessage NextLayout)  -- переключает на другое расположение, на текущем столе
    , ((mod4Mask, xK_Down), nextWS)            -- переключение на след. стол
    , ((mod4Mask, xK_Up), prevWS)            -- переключение на пред. стол
    -- переключает на другой монитор
    ]

 -- Мультимедийные клавиши управления звуком

 мультимедийные_клавиши = [
       ((0, xF86XK_AudioLowerVolume), kill)        -- уменьшает громкость
     , ((0, xF86XK_AudioRaiseVolume), kill)        -- увеличивает громкость
     , ((0, xF86XK_AudioMute), kill)            -- выключает звук
        ]

 -- Это набор для моей текущей клавиатуры
 -- Клавиши запуска приложений
 клавиши_запуска = [
      ((0, xF86XK_Close), kill)            -- Закрыть окно   
    , ((0, xF86XK_HomePage), spawn "firefox http://gimmor.blogspot.com/")    -- Web/Home
     , ((0, xF86XK_Mail), spawn "evolution")        -- Почта
    , ((0, xF86XK_Calculator), spawn "gcalctool")    -- Калькулятор
    , ((0, xF86XK_LogOff), spawn "gcalctool")    -- Выйти из съянса (не работает)
    , ((0, xF86XK_Sleep), spawn "gcalctool")    -- Спящий режим
       , ((0, xF86XK_Launch1), spawn "gcalctool")    -- Проверка
    , ((0, xF86XK_Favorites), spawn "nautilus")    -- Файлы
    , ((0, xF86XK_Messenger), spawn "skype")    -- Мессенджер
    ]

 -- Мои функциональные клавиши

 функциональные_клавиши = [
    ((0,xF86XK_Reply), spawn "gcalctool")         -- Ответ
    , ((0,xF86XK_Send), spawn "gcalctool")         -- Отправка
    , ((0,xF86XK_New), spawn "gcalctool")         -- Новое окно
    , ((0,xF86XK_Save), spawn "gcalctool")         -- Сохранение
    , ((0,xF86XK_MailForward), spawn "gcalctool")     -- Пересылка
    , ((0,xF86XK_Open), spawn "gcalctool")         -- Не работает
    , ((0,xK_Help), spawn "gcalctool")         -- Справка по Xmonad
    , ((0,xK_Print), spawn "scrot")          -- Скриншот экрана
    ]


 все_клавиши = concat [
    управляющие_клавиши,
    мультимедийные_клавиши,
    клавиши_запуска,
    функциональные_клавиши
    ]


 -- Клавиши для удаления
 
 удаляемые_клавиши = [ (mod4Mask .|. shiftMask, xK_c) 
      , (mod4Mask .|. shiftMask, xK_j) 
      , (mod4Mask .|. shiftMask, xK_k) 
      , (mod4Mask, xK_j) 
      , (mod4Mask, xK_k) 
      , (mod4Mask, xK_h) 
      , (mod4Mask, xK_l) 
      , (mod4Mask, xK_comma) 
      , (mod4Mask, xK_period) 
      ]

 ----------------------------------------------------------------------------------------
 --  VII. Секция привязки кнопок мыши
 ----------------------------------------------------------------------------------------
 -- клавиши_мыши = [ ((mod4Mask, button4),\_-> spawn "amixer set Master 3%+") 
 --     ,((mod4Mask, button5),\_-> spawn "amixer set Master 3%-") 
 --     ,((mod4Mask, button3),\_-> return()) 
 --     ,((mod4Mask, button1),\_-> return()) 
 --     ]

-----------------------------------------------------------------------------------------
--   VIII. Секция автозагрузки
-----------------------------------------------------------------------------------------



 ----------------------------------------------------------------------------------------
 --   IX. Секция конфигураций
 ----------------------------------------------------------------------------------------

 -- Моя конфигурация на основе конфигурации по-умолчанию

 рабочая_конфигурация = defaultConfig
     { manageHook = manageDocks
        <+> поведение_программ
                 <+> manageHook defaultConfig
     , layoutHook = avoidStruts $ расположение
     , terminal = "gnome-terminal --hide-menubar"
     , modMask = mod4Mask  -- меняем привязку клавиши, вместо alt будет  win
     , workspaces = рабочие_столы
     , normalBorderColor = цвет_рамки_обычного_окна
     , focusedBorderColor = цвет_рамки_выделенного_окна
     , borderWidth = 4
     , startupHook = return ()
     }  `additionalKeys` все_клавиши
        `removeKeys` удаляемые_клавиши
    -- `additionalMouseBindings` клавиши_мыши

 -- Экспериментальная конфигурация, для проверки разных возможностей
 экспериментальная_конфигурация = defaultConfig
     { manageHook = manageDocks
                <+> поведение_программ
                <+> manageHook defaultConfig
     , layoutHook = avoidStruts $ расположение
     , terminal = "urxvt"
     , modMask = mod4Mask      -- меняем привязку клавиши, вместо alt будет  win
     , workspaces = рабочие_столы
     }


 ----------------------------------------------------------------------------------------
 --    X. Секция главной функции main - точки входа в программу
 ----------------------------------------------------------------------------------------

 main = do
   spawn "setxkbmap -layout 'us,ru' -option grp:ctrl_shift_toggle -option grp_led:scroll"
   -- xmproc <- spawnPipe "/usr/bin/xmobar"
   xmonad $ рабочая_конфигурация



----------------------------------------------------------------------------------------
-- Дополнительная информация
----------------------------------------------------------------------------------------
-- Если при запуске xmonad не работает переключение клавиатуры
-- то временно исправить можно выполнив:
-- setxkbmap -layout "us,ru" -option grp:ctrl_shift_toggle -option grp_led:scroll


-- Ресурсы
-- http://www.haskell.org/haskellwiki/Xmonad/General_xmonad.hs_config_tips
--




Всё.
Чтобы оставить клавишу alt в качестве клавиши mod, надо убрать строку:

, modMask = mod4Mas
из рабочей конфигурации.
 

Плюсы XMonad

- Возможность настройки рабочего окружения и его сохранения между перезагрузками
- Возможность интеграции с окружением рабочего стола Gnome
- Возможность посмотреть на язык Haskell


Минусы XMonad

- Необходимость настройки начальной конфигурации
- Необходимость смотреть на язык Haskell
- Необходимость установить компоненты рабочего стола X Window - такие как Tray (trayer), StatusBar (xmobar), Menu (), Lock и соответственно настроить их взаимодействие
- Сложность настройки, например многооконных программ
- Неожиданности, для некторых программ


Выводы

Чистый xmonad только управляет окнами и поначалу может показаться не очень дружественным пользователю. Например, отсутствует строка статуса, список запущенных программ, отсутствует меню доступных программ (приходится запускать из консоли).
Со временем приходит понимание - лишнее всё это.


Осталось за кадром, подключение полосок состояний (xmobar, dzen), конфигурация gimp в многооконном режиме, различные интересные дополнения [см. Ресурсы п.14], повышающие удобство, автозагрузка рабочих программ.



Ресурсы

1. Официальный сайт языка Haskell. http://haskell.org/
2. О языке Haskell на Wikipedia. http://ru.wikipedia.org/wiki/Haskell
3. Описание Haskell 98 (на русском языке). http://www.haskell.ru/
4. Учебник по языку Haskell (на русском языке). http://anton-k.github.com/ru-haskell-book/book/home.html
5. Мягкое введение в haskell. http://www.rsdn.ru/article/haskell/haskell_part1.xml
6. Почему никто не использует функциональные языки. http://www.softcraft.ru/paradigm/fp/whynotfp.shtml
7. Hackage - свободная библиотека пакетов программ (функций). http://hackage.haskell.org/packages/hackage.html
8. Как выглядит XMonad. Снимки экрана. http://www.haskell.org/haskellwiki/Xmonad/Screenshots
9. Документация модуля xmonad. http://xmonad.org/xmonad-docs/xmonad/index.html
10. XMonad FAQ. http://www.haskell.org/haskellwiki/Xmonad/Frequently_asked_questions
11. Xmonad Tips. 
12. Настройка XMonad. http://ro-che.info/docs/xmonad/
13. Расширения XMonad. http://xmonad.org/xmonad-docs/xmonad-contrib/
14. Описание расширений XMonad и их применение (en). http://xmonad.org/xmonad-docs/xmonad-contrib/XMonad-Doc-Extending.html

15. Как Eax.me познакомился с xmonad. http://eax.me/xmonad/
16. Цвета текста и фона в Bash. http://tldp.org/HOWTO/Bash-Prompt-HOWTO/x329.html
17. Примеры конфигураций Xmonad: http://www.haskell.org/haskellwiki/Xmonad/Config_archive
18. Пользователи делятся информацией о Xmonad. http://www.linux.org.ru/tag/xmonad?offset=20

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