First commit

This commit is contained in:
Emmanuel Lepage Vallee 2013-02-20 12:11:17 -05:00
commit 66967c0fb2
3 changed files with 507 additions and 0 deletions

9
README Normal file
View File

@ -0,0 +1,9 @@
#Tyranic - A simple rule engine
Shifty was great and served us well since the early days of the Awesome 3.* series, but just as
many kid aged TV stars, it havn't grown that well. Many of it's, once unique, features are now
supported by the default awful.tag engine, adding legacy complexity to the code base and affecting
performance.
This is why Tyranic was created. It is a light rule engine offering pretty much the same rule system,
but without all the dynamic tag code. Note that dynamic tagging is now supported directly by awesome.

182
init.lua Normal file
View File

@ -0,0 +1,182 @@
local setmetatable = setmetatable
local print , pairs = print , pairs
local ipairs , type = ipairs , type
local string = string
local awful = require("awful")
local capi = {client = client , tag = tag ,
screen = screen , mouse = mouse }
module("tyranic")
-------------------------------INIT------------------------------
for _,sig in ipairs({"property::exclusive","property::init","property::volatile","property::focus_on_new","property::instances","property::match","property::class"})do
capi.tag.add_signal(sig)
end
-------------------------------DATA------------------------------
local class_client,matches_client = {},{}
--------------------------TYRANIC LOGIC--------------------------
--Turn tags -> matches into matches -> tags
local function fill_tyranic(tab_in,tab_out,value)
if tab_in and tab_out then
for i=1,#tab_in do
local low = string.lower(tab_in[i])
local tmp = tab_out[low] or {tags={},properties={}}
value.instances = value.instances or {}
tmp.tags[#tmp.tags+1] = value
tab_out[low] = tmp
end
end
end
--Load tags, this cannot be undone
local function load_tags(tyranic_tags)
for k,v in ipairs(tyranic_tags) do
if v.init ~= false then
v.instances = {}
local stype = type(v.screen)
if stype == "table" then
for k2,v2 in pairs(v.screen) do
if v2 <= capi.screen.count() then
v.screen = v2
v.instances[v2] = awful.tag.add(v.name,v)
end
end
elseif (v.screen or 1) <= capi.screen.count() then
v.instances[v.screen or 1] = awful.tag.add(v.name,v)
end
elseif v.volatile == nil then
v.volatile = true
end
fill_tyranic(v.class,class_client,v)
fill_tyranic(v.match,matches_client,v)
end
end
--Load property
local function load_property(name,property)
for k2,v2 in pairs(property) do
local key_type = type(k2)
local low = string.lower(key_type == "number" and v2 or k2)
class_client[low] = class_client[low] or {name=low,tags={},properties={}}
class_client[low].properties[name] = key_type == "number" and true or v2
end
end
--Match client
local function match_client(c, startup)
if not c then return end
local low = string.lower(c.class or "N/A")
local rules = class_client[low]
if rules then
--Force floating state if necessary
if rules.properties.floating ~= nil then
awful.client.floating.set(c, rules.properties.floating)
end
--Set other properties
for k,v in pairs(rules.properties) do
c[k] = v
end
--Add to the current tag if the client is intrusive, ignore exclusive
if rules.properties.intrusive == true then
local tag = awful.tag.selected(c.screen)
if tag then
c:tags({tag})
return
end
end
--TODO pre_match
--Add to matches
local tags = {}
for j=1,#(rules.tags or {}) do
local tag_tmp = rules.tags[j]
if not tag_tmp.instances[c.screen or 1] then
local cache = tag_tmp.screen
tag_tmp.screen = tag_tmp.force_screen == true and tag_tmp.screen or c.screen
c.screen = tag_tmp.screen
tag_tmp.instances[c.screen or 1] = awful.tag.add(tag_tmp.name,tag_tmp)
tag_tmp.screen = cache
end
tags[#tags+1] = tag_tmp.instances[c.screen or 1]
end
if #tags > 0 then
c:tags(tags)
if awful.tag.getproperty(tags[1],"focus_on_new") ~= false then
awful.tag.viewonly(tags[1])
end
return
end
--TODO post_match
end
--Add to the current tag if not exclusive
--TODO
--Last resort, create a new tag
class_client[low] = class_client[low] or {tags={},properties={}}
local tmp,tag = class_client[low],awful.tag.add(c.class,{name=c.class,volatile=true,screen=c.screen})
tmp.tags[#tmp.tags+1] = {name=c.class,instances = {tag},volatile=true,screen=c.screen}
c:tags({tag})
if awful.tag.getproperty(tag,"focus_on_new") ~= false then
awful.tag.viewonly(tag)
end
end
capi.client.connect_signal("manage", match_client)
capi.client.connect_signal("untagged", function (c, t)
if awful.tag.getproperty(t,"volatile") == true and #t:clients() == 0 then
local rules = class_client[string.lower(c.class or "N/A")]
for j=1,#(rules and rules.tags or {}) do
rules.tags[j].instances[c.screen] = rules.tags[j].instances[c.screen] ~= t and rules.tags[j].instances[c.screen] or nil
end
awful.tag.delete(t)
end
end)
-- awful.tag.withcurrent = function() end --Disable automatic tag insertion
awful.tag.withcurrent = function(c, startup)
local tags,old_tags = {},c:tags()
--Safety to prevent
for k, t in ipairs(old_tags) do
if awful.tag.getscreen(t) == c.screen then
tags[#tags+1] = t
end
end
--Necessary when dragging clients
if startup == nil and old_tags[1] and old_tags[1].screen ~= c.screen then --nil != false
local sellist = awful.tag.selectedlist(c.screen)
if #sellist > 0 then --Use already selected tag
tags = sellist
else --Select a tag
match_client(c, startup)
end
end
c:tags(tags)
end
--------------------------OBJECT GEARS---------------------------
local properties = {}
setmetatable(properties, {__newindex = function(table,k,v) load_property(k,v) end})
local function getter (table, key)
if key == "properties" then
return properties
end
end
local function setter (table, key,value)
if key == "tags" then
load_tags(value)
elseif key == "properties" then
properties = value
setmetatable(properties, {__newindex = function(table,k,v) load_property(k,v) end})
for k,v in pairs(tyranic_properties) do
load_property(k,v)
end
end
end
setmetatable(_M, { __call = function(_, ...) return end , __index = getter, __newindex = setter})

316
sample.rules.lua Normal file
View File

@ -0,0 +1,316 @@
local awful = require("awful")
-- }}}
local layouts =
{
awful.layout.suit.floating,
awful.layout.suit.tile,
awful.layout.suit.tile.left,
awful.layout.suit.tile.bottom,
awful.layout.suit.tile.top,
awful.layout.suit.fair,
awful.layout.suit.fair.horizontal,
awful.layout.suit.spiral,
awful.layout.suit.spiral.dwindle,
awful.layout.suit.max,
awful.layout.suit.max.fullscreen,
awful.layout.suit.magnifier
}
tags = {} --TODO remove
tyranic.tags = {
{
name = "Term",
init = true ,
exclusive = true ,
icon = utils.tools.invertedIconPath("term.png") ,
screen = {config.data().scr.pri, config.data().scr.sec} ,
layout = awful.layout.suit.tile ,
class = {
"xterm" , "urxvt" , "aterm","URxvt","XTerm"
},
match = {
"konsole"
}
} ,
{
name = "Internet",
init = true ,
exclusive = true ,
icon = utils.tools.invertedIconPath("net.png") ,
screen = config.data().scr.pri ,
layout = awful.layout.suit.max ,
class = {
"Opera" , "Firefox" , "Rekonq" , "Dillo" , "Arora",
"Chromium" , "nightly" , "Nightly" , "minefield" , "Minefield" }
} ,
{
name = "Files",
init = true ,
exclusive = true ,
icon = utils.tools.invertedIconPath("folder.png") ,
screen = config.data().scr.pri ,
layout = awful.layout.suit.tile ,
class = {
"Thunar" , "Konqueror" , "Dolphin" , "ark" , "Nautilus", }
} ,
{
name = "Develop",
init = true ,
exclusive = true ,
-- screen = {config.data().scr.pri, config.data().scr.sec} ,
icon = utils.tools.invertedIconPath("bug.png") ,
layout = awful.layout.suit.max ,
class ={
"Kate" , "KDevelop" , "Codeblocks", "Code::Blocks" , "DDD", "kate4" }
} ,
{
name = "Edit",
init = true ,
exclusive = true ,
-- screen = {config.data().scr.pri, config.data().scr.sec} ,
icon = utils.tools.invertedIconPath("editor.png") ,
layout = awful.layout.suit.tile.bottom ,
class = {
"KWrite" , "GVim" , "Emacs" , "Code::Blocks" , "DDD" }
} ,
{
name = "Media",
init = true ,
exclusive = true ,
icon = utils.tools.invertedIconPath("media.png") ,
layout = awful.layout.suit.max ,
class = {
"Xine" , "xine Panel" , "xine*" , "MPlayer" , "GMPlayer",
"XMMS" }
} ,
{
name = "Doc",
-- init = true ,
exclusive = true ,
icon = utils.tools.invertedIconPath("info.png") ,
-- screen = config.data().scr.music ,
layout = awful.layout.suit.max ,
class = {
"Assistant" , "Okular" , "Evince" , "EPDFviewer" , "xpdf",
"Xpdf" , }
} ,
-----------------VOLATILE TAGS-----------------------
{
name = "Imaging",
init = false ,
position = 10 ,
exclusive = true ,
icon = utils.tools.invertedIconPath("image.png") ,
layout = awful.layout.suit.max ,
class = {"Inkscape" , "KolourPaint" , "Krita" , "Karbon" , "Karbon14"}
} ,
{
name = "Picture",
init = false ,
position = 10 ,
exclusive = true ,
icon = utils.tools.invertedIconPath("image.png") ,
layout = awful.layout.suit.max ,
class = {"Digikam" , "F-Spot" , "GPicView" , "ShowPhoto" , "KPhotoAlbum"}
} ,
{
name = "Video",
init = false ,
position = 10 ,
exclusive = true ,
icon = utils.tools.invertedIconPath("video.png") ,
layout = awful.layout.suit.max ,
class = {"KDenLive" , "Cinelerra" , "AVIDeMux" , "Kino"}
} ,
{
name = "Movie",
init = false ,
position = 12 ,
exclusive = true ,
icon = utils.tools.invertedIconPath("video.png") ,
layout = awful.layout.suit.max ,
class = {"VLC"}
} ,
{
name = "3D",
init = false ,
position = 10 ,
exclusive = true ,
icon = utils.tools.invertedIconPath("3d.png") ,
layout = awful.layout.suit.max.fullscreen ,
class = {"Blender" , "Maya" , "K-3D" , "KPovModeler" , }
} ,
{
name = "Music",
init = false ,
position = 10 ,
exclusive = true ,
screen = config.data().scr.music or config.data().scr.pri ,
icon = utils.tools.invertedIconPath("media.png") ,
layout = awful.layout.suit.max ,
class = {"Amarok" , "SongBird" , "last.fm" ,}
} ,
{
name = "Down",
init = false ,
position = 10 ,
exclusive = true ,
icon = utils.tools.invertedIconPath("download.png") ,
layout = awful.layout.suit.max ,
class = {"Transmission" , "KGet"}
} ,
{
name = "Office",
init = false ,
position = 10 ,
exclusive = true ,
icon = utils.tools.invertedIconPath("office.png") ,
layout = awful.layout.suit.max ,
class = {
"OOWriter" , "OOCalc" , "OOMath" , "OOImpress" , "OOBase" ,
"SQLitebrowser" , "Silverun" , "Workbench" , "KWord" , "KSpread" ,
"KPres","Basket", "openoffice.org" , "OpenOffice.*" , }
} ,
{
name = "RSS",
init = false ,
position = 10 ,
exclusive = true ,
icon = utils.tools.invertedIconPath("rss.png") ,
layout = awful.layout.suit.max ,
class = {}
} ,
{
name = "Chat",
init = false ,
position = 10 ,
exclusive = true ,
screen = config.data().scr.sec or config.data().scr.sec ,
icon = utils.tools.invertedIconPath("chat.png") ,
layout = awful.layout.suit.tile ,
class = {"Pidgin" , "Kopete" ,}
} ,
{
name = "Burning",
init = false ,
position = 10 ,
exclusive = true ,
icon = utils.tools.invertedIconPath("burn.png") ,
layout = awful.layout.suit.tile ,
class = {"k3b"}
} ,
{
name = "Mail",
init = false ,
position = 10 ,
exclusive = true ,
-- screen = config.data().scr.sec or config.data().scr.pri ,
icon = utils.tools.invertedIconPath("mail2.png") ,
layout = awful.layout.suit.max ,
class = {"Thunderbird" , "kmail" , "evolution" ,}
} ,
{
name = "IRC",
init = false ,
position = 10 ,
exclusive = true ,
screen = config.data().scr.irc or config.data().scr.pri ,
init = true ,
spawn = "konversation" ,
icon = utils.tools.invertedIconPath("irc.png") ,
force_screen= true ,
layout = awful.layout.suit.fair ,
class = {"Konversation" , "Botch" , "WeeChat" , "weechat" , "irssi"}
} ,
{
name = "Test",
init = false ,
position = 99 ,
exclusive = false ,
screen = config.data().scr.sec or config.data().scr.pri ,
leave_kills = true ,
persist = true ,
icon = utils.tools.invertedIconPath("tools.png") ,
layout = awful.layout.suit.max ,
class = {}
} ,
{
name = "Config",
init = false ,
position = 10 ,
exclusive = false ,
icon = utils.tools.invertedIconPath("tools.png") ,
layout = awful.layout.suit.max ,
class = {"Systemsettings", "Kcontrol" , "gconf-editor"}
} ,
{
name = "Game",
init = false ,
screen = config.data().scr.pri ,
position = 10 ,
exclusive = false ,
icon = utils.tools.invertedIconPath("game.png") ,
force_screen= true ,
layout = awful.layout.suit.max ,
class = {"sauer_client" , "Cube 2$" , "Cube 2: Sauerbraten" ,}
} ,
{
name = "Gimp",
init = false ,
position = 10 ,
exclusive = false ,
icon = utils.tools.invertedIconPath("image.png") ,
layout = awful.layout.tile ,
nmaster = 1 ,
incncol = 10 ,
ncol = 2 ,
mwfact = 0.00 ,
class = {}
} ,
{
name = "Other",
init = true ,
position = 15 ,
exclusive = false ,
icon = utils.tools.invertedIconPath("term.png") ,
max_clients = 5 ,
screen = {3, 4, 5} ,
layout = awful.layout.suit.tile ,
class = {}
} ,
{
name = "MediaCenter",
init = true ,
position = 15 ,
exclusive = false ,
icon = utils.tools.invertedIconPath("video.png") ,
max_clients = 5 ,
screen = config.data().scr.media or config.data().scr.pri ,
init = "mythfrontend" ,
layout = awful.layout.suit.tile ,
class = {"mythfrontend" , "xbmc" ,}
} ,
}
tyranic.properties.intrusive = {
"ksnapshot" , "pinentry" , "gtksu" , "kcalc" , "xcalc" ,
"feh" , "Gradient editor", "About KDE" , "Paste Special", "Background color",
"kcolorchooser" , "plasmoidviewer" , "plasmaengineexplorer" , "Xephyr" , "kruler" ,
}
tyranic.properties.floating = {
"MPlayer" , "pinentry" , "ksnapshot" , "pinentry" , "gtksu" ,
"xine" , "feh" , "kmix" , "kcalc" , "xcalc" ,
"yakuake" , "Select Color$" , "kruler" , "kcolorchooser", "Paste Special" ,
"New Form" , "Insert Picture" , "kcharselect", "mythfrontend" , "plasmoidviewer"
}
tyranic.properties.ontop = {
"Xephyr" , "ksnapshot" , "kruler"
}
tyranic.properties.size_hints_honor = { xterm = false, URxvt = false, aterm = false, sauer_client = false, mythfrontend = false}