Understanding Rules/ru

Примечания переводчика, для полного понимания материала приведенного на этой странице рекомендуется знание основ языка Lua. Для ознакомления с Lua на русском языке, есть [руководство].

В этой статье описываются правила(rules) которые появились в Awesome и способы работы с ними.

Приступая к работе
Когда вы впервые открыли rc.lua для ознакомления или редактирования, вы наверняка обратили внимание на следующий код:

awful.rules.rules = { -- All clients will match this rule. { rule = { }, properties = { border_width = beautiful.border_width, border_color = beautiful.border_normal, focus = true, keys = clientkeys, buttons = clientbuttons } }, { rule = { class = "MPlayer" }, properties = { floating = true } }, { rule = { class = "pinentry" }, properties = { floating = true } }, { rule = { class = "gimp" }, properties = { floating = true } }, -- Set Firefox to always map on tags number 2 of screen 1. -- { rule = { class = "Firefox" }, --  properties = { tag = tags[1][2] } }, }

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

Основные принципы
В своей основе, 'awful.rules.rules' содержит массив инструкций, где каждая инструкция состоит из двух частей.

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

Выбор окна
Awesome может проверять различные свойства(properties) окон, чтобы найти нужное нам окно для дальнейших действий над ним. Существует четыре способа, которыми вы можете выйти на нужное вам окно:

rule

 * При сравнении окон, они должны соотвестовать всем свойствам, определенным в массиве(array) данного правила(rule).

{ rule = { class = {"MPlayer", "pinentry", "Gimp"} }, в данном случае не будет выбрано ни одно окно, так как не может быть 3х приложений являющихся родителями одного окна 

rule_any

 * При сравнении окон, они должны соответсвовать одному или более свойствам определенным в массиве данного правила, т.е. по принципу "любое из"

{ rule_any = { class = {"MPlayer", "pinentry", "Gimp"} }, в данном случае будет выбрано любое из окон, родителями которого являются указанные в списке приложения 

except

 * Из найденных окон, попадающие под правило rule или rule_only исключаются окна, которые попадают под все свойства которые прописаны в массиве except, т.е. по принципу "все кроме ...всех перечисленных".

{ rule_any = { class = { "psi", "Psi" } }, except = { instance = "main" }, в данном случае будут выбраны все окна приложения Psi, кроме главного

except_any

 * Из найденных окон, попадающие под правило rule или rule_any исключаются окна, которые попадают под одно или более свойств которые прописаны в массиве except, т.е. по принципу "все кроме одного/нескольких из перечисленных"

{ rule = { class = { "XTerm" } }, except_any = { instance = "mail", instance = "vim" }, в этом примере будут выбраны окна всех терминалов, кроме имеющих свойство mail или vim

Значения 'rule' и другие являются множеством(array), в которых перечисляются все необходимые вам свойства окон Awesome для их сравнения. Этот массив(array) может быть любой длинны, включая нулевую(пустое). И имеет следующий синтаксис:

{ rule = { [ property = value [, property = value, ... ] ] } }

Где property это имя из списка свойства окон.

Если правило(rule) имеет нулевое(пустое) значение, то оно соотвествует всем окнам. А 'except' с нулевыми значениями вообще не исключает окна.

При сравнении, каждое правило, сравнивается с каждым окном, без завершения при нахождении первого подходящего значения. Все rule сравниваются со всеми окнами; окно может соотвестовать более чем одному rule. Для каждого подходящего 'rule'(правила) соотвествующему окну посылаются указанные модификации. До тех пор пока не будет пройден весь список правил.

Для свойств окна, являющихся строками, значения свойств установленные в rule и прочих сравниваются со свойствами окон используя функцию Lua string.match, которая производит сравнение подстроки и шаблона. Таким образом rule(правилу) содержащему '{ class = "x" }' будут соответсвовать все окна у которых символ "x" присутсвует где либо в свойстве окна 'class'.

Модификация окон
После того, как нужное нам окно найдено, обычно мы хотим сделать с ним что либо. Для этого существует 2 способа указать Awesome как изменить окно.

properties
На сегодняшний день, наиболее распространным способом является массив(array) свойств(properties) и значений окна. Для каждого значнения в массиве свойств(properties) Awesome присваивает значение соответсвующему свойству в найденных окнах.

Синтаксис для properties следующий:

{ properties = { property = value [, property = value, ... ] } }

Где property это название свойств окна.

property также можется являться и функция Lua. Функция вызывается Awesome как первый аргумент, а value это второй аргумент.

callback
(Функция callback считается устаревшей.)

Вы можете определить функцию Lua, которая будет вызвана когда окно будет подходить по параметрам; в этом случае клиентское окно передается в функцию как аргумент. Это можно использовать для создания более сложных операций с окном, чем при использовании простых свойст. Как properties, так и callback принимает масссив, в котором вы можете определить любое колличество функций, которые вызываются при нахождении соотвествующего окна.

Синтаксис для callback слудующий:

{ callback = { function [, function, ... ] }

Где function это любые функции Lua которые Awesome принимает в качестве аргументов.

Свойства окон
Полный список всех properties которые известны Awesome и могут быть изменены, также их можно найти конце страницы Документация Lua API. Имена большинства этих свойств интуитивно понятны.

К сожалению, некоторые из этих свойств, являются встроенными значениями X Windows, некоторые из которых сравнительно мало понятны и описание на странице Lua API довольно скудное. Однако для создания эффективных правил(rule), вам необходимо понимать некоторые из них. Программа xprop, которая является стандартной, для всех X Windows-based систем, может быть полезной для понимания некоторых из них. Для использвания 'xprop' необходимо:
 * Откройте терминал.
 * Наберите команду xprop и нажмите Enter. Переместите курсор мыши на нужное вам окно.
 * Используя мышь, щелкните на заинтересовавшей вас точке окна. После этого, свойства X Windows для этого окна будут напечатаны в терминале.

В частности 'xprop', может быть чрезычайно полезен для понимания разницы между class, name , и instance свойствами.

Ниже описан небольшой список поддерживаемых в Awesome window properties, а также их краткое описание.

Как правило содержит заголовок окна, в любой заданный момент. Свойство name окна, это строка, которая может быть изменена программой в любое время. Поскольку многие программы, как известно, часто изменяют это свойство (наглядным примером может являться Firefox), это rule(правило) имеет ограниченное применение.

В выводе xprop, значением соответсвующим этому свойству(property) будет WM_NAME.

Это имя является уникальным для программы -- обычно это имя программы записанное в Camel(верблюжей/горбатой)-версии (Firefox, XTerm, Nm-manager, Keepassx и т.д.). class - этот параметр является строкой, только для чтения, и жестко определяется программой создавшей его -- это значит, что программа определяет какое значение class у нее будет, и после этого значение не может быть изменено. Т.е. независимо от того, сколько экзепмляров терминала XTerm вы запустили, и какие они имеют заголовки, все его окна будут иметь одинаковое значение class ("XTerm"). Таким образом, class можно использовать, для того чтобы однозначно ассоциировать 'rule'(правило) с конкретной программой.

В выводе xprop, свойству class будет соответствовать второе значение WM_CLASS.

Забавный параметр. instance - также является строкой. Может быть установлено любое значение при запуске программы.

instance является особенностью системы X Windows, которая практически не используется в наше время. Это позволяет разделять окна, которые имеют общий исполняемый файл, но сейчас используются в различных целях/ролях. Например, у вас есть окно XTerm, которое вы испльзуете только для чтения почты, поэтому вы можете изменить его property(свойство) instance, таким образом, чтобы отличать его от других окон XTerm.

Большинство программ X Windows, позволяют изменять значение 'instance' используя аргумент командной строки -name. Если вы не измените значение instance, оно по умолчанию будет установлено как argv[0] (имя используемое вами для запуска программы).

Есть исключения из этого правила, в первую очередь, Firefox. class для Firefox "Firefox". Тем не менее, instance для всех окон браузера Firefox установлен "Navigator". Вероятно, это историческое отступление от Mozilla (прародителя Firefox), когда он был не только браузером, но также и почтовым клиетом и редактором HTML. Все окна открытые в Mozilla, будут иметь class Mozilla, но окна почтовика и редактора HTML, будут иметь другие значения в 'instance'. Так что, если вы хотите изменить properties для окон браузера, но не трогать почтовик, вы должны использовать значение instance равным "Navigator".

В выводе xprop, свойству class будет соответсвовать первое значение WM_CLASS.

Вы можете поиграться с xprop и посмотреть как взаимосвязаны между собой instance и class. В качестве примера, откройте командную оболочку и запустите xterm:

$ xterm

Затем, посмотрите его используя :

WM_CLASS(STRING) = "xterm", "XTerm"

Теперь запустите xterm с другим значением instance используя аргумент -name:

$ xterm -name vim

Теперь xprop выведет следующее:

WM_CLASS(STRING) = "vim", "XTerm"

В завершение, просто для смеха, создайте ссылку на xtrerm, а затем запустите xterm используя ссылку:

$ ln -s /usr/bin/xterm barfoo $ ./barfoo

И xprop выведет следующее:

WM_CLASS(STRING) = "barfoo", "XTerm"

Типы окон. type это строка, которая может принимать одно из слудующих значений:
 * (drag & drop)
 * (drag & drop)
 * (drag & drop)
 * (drag & drop)
 * (drag & drop)
 * (drag & drop)
 * (drag & drop)
 * (drag & drop)
 * (drag & drop)
 * (drag & drop)
 * (drag & drop)
 * (drag & drop)
 * (drag & drop)

type окон можно менять, но это может привести к непредсказуемым последствиям, поэтому делать это не рекомендуется.

Уникальный идентификационный номер (ID) 'именно этого окна и никакого другого. Значение 'window' является целым уникальным числом, только для чтения, и оно присваивается окну при его создании. ID существует на протяжении всей жизни окна, и уничтожается при его закрытии. ID окна, никогда повторно не выделяется в течении одной сессии.

Иногда устанавливается приложением, но как правило не используется в Awesome. (Другие оконные менеджеры могут использвать это property(свойство) совместно с name и class, для уникальной идентификации окон, чтобы использовать их для сохранения и восстановления после восстановления сессии).

В выводе xprop, свойству role соотвествует значение WM_WINDOW_ROLE, если оно существует.

Дополнительные свойства
В дополнение к properties окон описанных в документации Lua API, существуют также properties обеспечиваемые библиотекой awful:


 * Boolean; изменяет атрибут плавающего окна.
 * Boolean; изменяет атрибут плавающего окна.


 * Строка; изменяет tag окна на заданное значение.
 * Строка; изменяет tag окна на заданное значение.


 * Строка; изменяет рабочий стол на заданный tag.
 * Строка; изменяет рабочий стол на заданный tag.


 * Целое; изменяет положение и/или размер окон.
 * Целое; изменяет положение и/или размер окон.
 * Целое; изменяет положение и/или размер окон.
 * Целое; изменяет положение и/или размер окон.
 * Целое; изменяет положение и/или размер окон.


 * Boolean; когда установленно true, передает фокус на заданное окно. Это свойство всегда определяется последним, независимо от порядка, должно быть описано в массиве properties.
 * Boolean; когда установленно true, передает фокус на заданное окно. Это свойство всегда определяется последним, независимо от порядка, должно быть описано в массиве properties.

Разбираем rc.lua
Теперь мы имеем базовое понимание rules(правил), и мы можем лучше интерпретировать правила(rule), установленные по умолчанию в Awesome. Давайте вглянем на них еще раз:

awful.rules.rules = { -- Все приложения будут соотвествовать следующему правилу { rule = { }, properties = { border_width = beautiful.border_width, border_color = beautiful.border_normal, focus = true, keys = clientkeys, buttons = clientbuttons } }, -- Правила для других классов окон { rule = { class = "MPlayer" }, properties = { floating = true } }, { rule = { class = "pinentry" }, properties = { floating = true } }, { rule = { class = "gimp" }, properties = { floating = true } }, -- Устанавливаем Firefox, на tags номер 2 экрана 1. -- { rule = { class = "Firefox" }, --  properties = { tag = tags[1][2] } }, }

Давайте разберем этот код по порядку. Опять же, повторим, что каждое правило(rule) состоит из двух частей -- часть сравнения и командная чать. Первая сравнительная часть следующая:

{ rule = { },

Как уже упоминалось выше, rule с пустым массивом свойств(properties) соотвествует всем окнам. Поэтому, следующая, командная часть будет применена ко всем окнам:

properties = { border_width = beautiful.border_width, border_color = beautiful.border_normal, focus = true, keys = clientkeys, buttons = clientbuttons } },

Здесь устанавливаются properties(свойства), поэтому массив содержащий значения свойств будет присвоен соотвествующим окнам (в нашем случае всем окнам):


 * Толщина границы и цвет окон, устанавливаются равные значениям текущей темы, загруженные библиотекой.
 * Толщина границы и цвет окон, устанавливаются равные значениям текущей темы, загруженные библиотекой.
 * Толщина границы и цвет окон, устанавливаются равные значениям текущей темы, загруженные библиотекой.


 * Фокус воода передается окну. Это может показаться немного запутанным, пока вы считаете, что эти правила('rule') применяются только при запуске Awesome. Также эти правила применяются и при создании новых окон. Т.к. мы хотим, чтобы вновь открываемые окна, также получали фокус ввода, мы вставляем это 'propery'(свойство) здесь.
 * Фокус воода передается окну. Это может показаться немного запутанным, пока вы считаете, что эти правила('rule') применяются только при запуске Awesome. Также эти правила применяются и при создании новых окон. Т.к. мы хотим, чтобы вновь открываемые окна, также получали фокус ввода, мы вставляем это 'propery'(свойство) здесь.


 * Здесь мы привязываем созданные ранее  и   к окну. Это делает пользовательский интерфейс(UI) всех окон единым.
 * Здесь мы привязываем созданные ранее  и   к окну. Это делает пользовательский интерфейс(UI) всех окон единым.
 * Здесь мы привязываем созданные ранее  и   к окну. Это делает пользовательский интерфейс(UI) всех окон единым.

Остальные правила(rule) довольно просты. Как уже упоминалось ранее, досрочный выход из обработки правил(rule) отсутсвует. Все правила(rule) последовательно проверяются для всех окон. Так, что, соотвествие предыдущего правила окну, не означает конец обработки списка правил. Следующее  :

{ rule = { class = "MPlayer" }, properties = { floating = true } },

Для всех окон у которых  содержат "MPlayer", устанавливается плавающий атрибут для окна. Это предотвращает от автоматического измения размера, который может произовдить Awesome.

{ rule = { class = "pinentry" }, properties = { floating = true } },

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

{ rule = { class = "gimp" }, properties = { floating = true } },

Для всех окон у которых  содержит "gimp", устанавливаем свойство плавающих окон.

Но... Подождите секунду; это выглядит странным для меня. По соглашению описанному выше, большинство названий в  начинаются с заглавной буквы. Давайте на самом деле запустим GIMP и проверим его с помощью xprop. GIMP фактически открывает 3 окна, поэтому сначала мы проверим главное окно:

WM_CLASS(STRING) = "gimp", "Gimp"

Интересно. Свойство  в GIMP - "gimp", но   соответствует "Gimp" (с заглавной). Другие два окна, имеют те же значения  и. Это означает, что  указанное выше не будет работать.

Хорошо, давайте исправим его:

{ rule = { class = "Gimp" }, properties = { floating = true } },

Теперь лучше.

Кстати, оказывается, что GIMP использует свойство  для различия собсвенных окон, поэтому вы может испльзовать в своих правилах(rule):

Main Image Window: WM_WINDOW_ROLE(STRING) = "gimp-image-window"

Toolbox Window: WM_WINDOW_ROLE(STRING) = "gimp-toolbox"

Dock Window: WM_WINDOW_ROLE(STRING) = "gimp-dock"

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

{ rule_any = { class = {"MPlayer", "pinentry", "Gimp"} }, properties = { floating = true } },

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

Использование except
{ rule_any = { class = { "psi", "Psi" } }, except = { instance = "main" }, callback = awful.client.setslave },

Это правило('rule') для клиента Psi IM. Оно указывает, что каждое окно Psi, будет установлено как вторичное, за исключением списка контактов, которое устанавливается главным. Это позволяет списку контактов всегда оставатся видимым и на том же месте, в то время как окна чатов будут открываться и закрываться, при условии, что tag был правильно настроен.

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

Здесь вы можете видеть, что class (вторая строка WM_CLASS) равна "psi" для первых двух, но "Psi" с заглавной P для третьего. Так что для того, чтобы соответствовать всем этим окнам, мы должны использовать rule_any с обоими вариантами, поэтому правило будет соответствовать любому из указанных названий классов(class).

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

Теперь у нас есть правило, которое будет соотвестовать всех окнам Psi, за исключением списка контактов, и которое будет вызывать функцию awful.client.setslave. Она устанавливает окна Psi вторичными, за исключением списка контактов, которое остается главным.

Похожие страницы

 * awful.rules
 * Документация Lua для модуля awful.rules, которая описывает функциональность правил(rule).


 * Примеры правил для приложений
 * Несколько правил для основных приложений, в основном помечаются плавающим режимом, в случае необходимости.