Run or raise/ru

Если у вас есть приложения помещенные в быстрый запуск и вы не хотите чтобы они запускались более чем один раз (например Firefox или Pidgin),то функция run_or_raise позволяет вам запустить приложение, если оно еще не запущено или переключается на запущенное окно. При наличии нескольких окон у приложения, например как у IRC клиента, эта функция будет перключаться между его окнами. Окна приложения могут быть сгруппированы и вы можете циклически переключаться между ними исползуя их атрибуты class, instance или name.

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

Существует два способа реализовать описанные возможности. Первый способ, вы можете весь код добавить в файл конфигурации ~/.config/awesome/rc.lua. Вторым способом является модульная структура, и меньше засоряет файл конфигурации.

 01.01.2013: Оба способа полностью совместимы с awesome 3.5 

Модульный подход
Вам необходимо будет создать 2 файла для этого способа. Файл aweror.lua содержит функциональные блоки, а в ror.lua перечислены горячие клавиши.

Вы можете поместить aweror.lua в папку с библиотеками awesome (/usr/local/share/awesome/lib/ или /usr/share/awesome/lib/ в зависимости от вашей системы) или же в каталог с пользовательскими нистройками (~/.config/awesome/).

Файл ror.lua содержит определенные пользователем настройки клавиш, и поэтому должен располагаться в каталоге с конфигурационными файлами, в (~/.config/awesome), если вы конечно хотите использовать клавиатурные сочетания. Отредактируйте клавиатурные сочетания в соотвествии с вашими желаниями (формат описан в файле).

После размещения файлов aweror.lua и ror.lua в пользовательских каталогах, необходимо будет немного отредактировать ~/.config/awesome/rc.lua. В этом файле мы будем испльзовать команду root.keys(globalkeys) для установки пользовательских клавиатурных сочетаний. Функция aweror должна быть загружена и сочетания клавиатуры для 'run or raise' нужно добавить перед разделом с командами globalkeys. В строки перед root.keys(globalkeys) нам необходимо добавить эти две команды: -- загрузить функцию 'run or raise' local ror = require("aweror")

-- создаем и добавляем клавиатурные сочетания 'run or raise' в глобальную клавиатурную таблицу globalkeys = awful.util.table.join(globalkeys, ror.genkeys(modkey))

root.keys(globalkeys)

После редактирования файла rc.lua и добавления файлов aweror.lua и ror.lua клавиатурные сокращения 'run or raise' будут отлично работать. Теперь вы можете переключать окна Firefox или Emacs, и все остальные нажатимем "Modkey + key".

Содержание файла aweror.lua: -- aweror.lua -- Save this file as "aweror.lua" in awesome's system library directory "/usr/local/share/awesome/lib", -- "/usr/share/awesome/lib", or your own config directory "~/.config/awesome/". -- You will also need a "ror.lua" file (contains your key bindings) in your config directory. -- Now you need to generate and add the keybindings in your ~/.config/awesome/rc.lua -- In the rc.lua file there will be a "root.keys(globalkeys)" command that sets -- your keys, you need to add the following lines just before that command: -- -- local ror = require("aweror") -- globalkeys = awful.util.table.join(globalkeys, ror.genkeys(modkey))

-- получаем клавиатурные сочетания из нашего отдельного файла ror.lua require("ror")

local awful= require("awful") local client=client local pairs=pairs local table=table local allt1=table5 local print=print local USE_T = true --local USE_T = false

local aweror = {}

function aweror.run_or_raise(cmd, properties) local clients = client.get local focused = awful.client.next(0) local findex = 0 local matched_clients = {} local n = 0 for i, c in pairs(clients) do     --создаем список соотвествующих/попадающий под условия(matched) приложений if match(properties, c) then n = n + 1 matched_clients[n] = c        if c == focused then findex = n        end end end if n > 0 then local c = matched_clients[1] -- если фокус ввода установлен на требуемом окне, перключаем его на следующее окно в списке if 0 < findex and findex < n then c = matched_clients[findex+1] end local ctags = c:tags if #ctags == 0 then -- ctags пуст, показываем приложение в текущем теге local curtag = awful.tag.selected awful.client.movetotag(curtag, c)     else -- в противном случае переключаемся на тег с первым окном клиента awful.tag.viewonly(ctags[1]) end -- И передаем приложению фокус ввода client.focus = c     c:raise return end awful.util.spawn(cmd) end

-- Возвращаем true если все части в table1 присутствуют в table2 function match (table1, table2) for k, v in pairs(table1) do     if table2[k] == nil or (table2[k] ~= v and not table2[k]:find(v)) then return false end end return true end

function genfun(t3) local cmd=t3[1] local rule=t3[2] local flag=t3[3] local table1={} s1="class" if flag then s1=flag end table1[s1]=rule return function aweror.run_or_raise(cmd,table1) end end

function aweror.genkeys(mod1) rorkeys = awful.util.table.join for i,v in pairs(allt1) do   modifier="" if i:len > 1 then modifier=i:sub(1, i:find("-")-1) i=i:sub(-1,-1) end rorkeys = awful.util.table.join(rorkeys,     awful.key({ mod1, modifier}, i, genfun(v))) end return rorkeys end

return aweror

Пример файла клавиатурных сочетаний ror.lua (отредактируйте по вашему желанию): -- ror.lua -- Поместите файл в каталог ~/.config/awesome/ -- Данный файл содержит клавиатурные сокращения 'run or raise' для aweror.lua -- Формат таблицы: ["key"]={"function", "match string", "optional attribute to match"} -- "key" может включать модификаторы "Control-", "Shift-", и "Mod1-" (например "Control-z") -- Также "key" можно связать с Mod, используя для этого "modkey + key". (например для приведенного выше примера это будет modkey+Control+z) -- "function" соотвествует приложению, которое нужно запустить, если окно приложения не будет найдено. -- Слудующий параметр, это обычные атрибуты, такие как "class","instance", или "name". Если атрибут не определен явно, то по умолчанию будет исползван "class". -- "Строка соответствия" может искать значение в подстроке. Поэтому, например "Firefox" будет соответсвовать "blah Firefox blah" -- Используйте xprop для получения информации об окне. В значении WM_CLASS(STRING) вы получите "instance", "class". -- Значение WM_NAME(STRING) соотвествует названию выбранного окна (обычно чтото соответсвующее заголовку веб страницы -- браузера, или имени файла в emacs).

table5={ ["Control-z"]={"google-chrome --app=http://www.rdio.com","www.rdio.com", "instance"}, ["e"]={"emacsclient -a emacs -n -c","Emacs"}, ["w"]={"firefox","Firefox"}, ["v"]={"firefox -new-window 'http://www.evernote.com/Home.action?login=true#v=l&so=mn'","Evernote", "name"}, ["g"]={"firefox -new-window 'http://mail.google.com/mail/'","Gmail","name"}, ["x"]={"xterm","xterm", "instance"}, ["f"]={"xterm -name mcTerm -e mc -d","mcTerm", "instance"}, ["Shift-s"]={"xterm -name rootTerm -cr red -title rootTerm -e su","rootTerm", "instance"}, ["t"]={"xterm -name htopTerm -e htop","htopTerm","instance"}, ["b"]={"xterm -name rtorrentTerm -e rtorrent","rtorrentTerm","instance"}, ["z"]={"xterm -name mocpTerm -e mocp","mocpTerm", "instance"} }

Другой пример, все соотвествует атрибутам класса по умолчанию -- ror.lua table5={ ["f"]={"firefox","Namoroka"}, ["a"]={"chromium --user-data-dir=/dev/shm/goo", "Chromium" }, ["s"]={"xterm -class Screen -e screen -xRRS xterm ", "Screen" }, ["v"]={"gvim", "GVIM"}, ["e"]={"emacs", "Emacs"} }

Изменяем только rc.lua
В этом способе, все изменения делаются в файле конфигурации пользователя ~/.config/awesome/rc.lua.

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

Определения клавиш выглядит следующим образом:

awful.key({ modkey, }, "KEY", function run_or_raise("FUNCTION", { ATTRIBUTE = "MATCH STRING" }) end),

KEY = the desired key to be bound

FUNCTION = the function to run if no client windows match

ATTRIBUTE = the window attribute to match. Either class, instance, or name.

MATCH STRING = the substring to match in the attribute

Некоторые примеры приведены ниже.

--- Spawns cmd if no client can be found matching properties -- If such a client can be found, pop to first tag where it is visible, and give it focus -- @param cmd the command to execute -- @param properties a table of properties to match against clients. Possible entries: any properties of the client object function run_or_raise(cmd, properties) local clients = client.get local focused = awful.client.next(0) local findex = 0 local matched_clients = {} local n = 0 for i, c in pairs(clients) do     --make an array of matched clients if match(properties, c) then n = n + 1 matched_clients[n] = c        if c == focused then findex = n        end end end if n > 0 then local c = matched_clients[1] -- if the focused window matched switch focus to next in list if 0 < findex and findex < n then c = matched_clients[findex+1] end local ctags = c:tags if #ctags == 0 then -- ctags is empty, show client on current tag local curtag = awful.tag.selected awful.client.movetotag(curtag, c)     else -- Otherwise, pop to first tag client is visible on        awful.tag.viewonly(ctags[1]) end -- And then focus the client client.focus = c     c:raise return end awful.util.spawn(cmd) end

-- Returns true if all pairs in table1 are present in table2 function match (table1, table2) for k, v in pairs(table1) do     if table2[k] ~= v and not table2[k]:find(v) then return false end end return true end

Пример использования:

Нижеприведенные клавиатурные сочетания, которые я использую для google-chrome, используют  поиск соотвествия по атрибуту NAME. Это позволяет мне переключаться между окнами браузера раздельно от вкладок с gmail, и evernote (открытых в chrome). Горячие клавиши запускают, или переключают evernote или gmail достаточно осторожно.

Добавьте что-то подобное приведенному ниже примеру, в таблицу глобальных клавиатурных сокращений в файле rc.lua: awful.key({ modkey, }, "f", function run_or_raise("xterm -name mcTerm -e mc -d", { instance = "mcTerm" }) end), awful.key({ modkey, }, "w", function run_or_raise("google-chrome", { name = "Google Chrome" }) end), awful.key({ modkey, }, "v", function run_or_raise("google-chrome --app='http://www.evernote.com/Home.action?login=true'", { name = "Evernote" }) end), awful.key({ modkey, }, "g", function run_or_raise("google-chrome --app='http://mail.google.com/mail/'", { name = "Gmail" }) end),

Интеграция с меню
Раздел запуск или переключение используя dmenu на странице Using dmenu приводит очень простой пример, показывающий как использовать dmenu в "запуске или переключении". Хотя в примере напрямую не используется "запуск или переключение", вы легко сможете его перенастроить.