more compliant conf parser and smart autominimization of apps on boot
This commit is contained in:
parent
08c4d52480
commit
fc811359ae
|
@ -30,23 +30,22 @@ shell = "zsh"
|
|||
# Format: <modifier>(+<modifier>+...)+<key> = "<command or :internal.function>"
|
||||
# "modkey" as modifier will be substituted for modkey variable in [global]
|
||||
[keys]
|
||||
modkey+Up = ":root.client_next"
|
||||
modkey+Down = ":root.client_previous"
|
||||
modkey+Control+Up = ":root.screen_next"
|
||||
modkey+Control+Down = ":root.screen_previous"
|
||||
modkey+Tab = ":root.client_swap"
|
||||
modkey+Return = ":root.spawn_terminal"
|
||||
modkey+Shift+Return = ":root.spawn_browser"
|
||||
"modkey+Up" = ":root.client_next"
|
||||
"modkey+Down" = ":root.client_previous"
|
||||
"modkey+Control+Up" = ":root.screen_next"
|
||||
"modkey+Control+Down" = ":root.screen_previous"
|
||||
"modkey+Tab" = ":root.client_swap"
|
||||
"modkey+Return" = ":root.spawn_terminal"
|
||||
"modkey+Shift+Return" = ":root.spawn_browser"
|
||||
|
||||
# Client keys only work if a focused client exists
|
||||
modkey+Shift+c = ":client.kill"
|
||||
modkey+t = ":client.cycle_screen"
|
||||
modkey+o = ":client.ontop"
|
||||
modkey+b = ":client.below"
|
||||
modkey+f = ":client.fullscreen"
|
||||
modkey+n = ":client.minimize"
|
||||
modkey+m = ":client.maximize"
|
||||
|
||||
"modkey+Shift+c" = ":client.kill"
|
||||
"modkey+t" = ":client.cycle_screen"
|
||||
"modkey+o" = ":client.ontop"
|
||||
"modkey+b" = ":client.below"
|
||||
"modkey+f" = ":client.fullscreen"
|
||||
"modkey+n" = ":client.minimize"
|
||||
"modkey+m" = ":client.maximize"
|
||||
]]
|
||||
for k,v in pairs(parsers.conf(data)) do
|
||||
print("Block: ["..k.."]")
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
local parsers = {}
|
||||
|
||||
local function split_strings(text)
|
||||
-- probably the cleanest function to split by strings i've written
|
||||
-- probably the cleanest function to split by strings i've written to date
|
||||
local split = {}
|
||||
while text:find("\"") do
|
||||
local strstart = text:find("\"")
|
||||
|
@ -86,48 +86,74 @@ parsers.yaml_pseudo = function(cfgtext)
|
|||
return struct
|
||||
end
|
||||
|
||||
local function quotestrip(txt)
|
||||
if (txt:sub(1,1):match("['\"]"))
|
||||
and (txt:sub(-1,-1) == txt:sub(1,1)) then
|
||||
return txt:sub(2,-2)
|
||||
else
|
||||
return txt
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
parsers.conf = function(cfgtext)
|
||||
-- Conf style parser (not exactly TOML)
|
||||
cfgtext = cfgtext:gsub("#[^\n]*","")
|
||||
local split_by_strings,err = split_strings(cfgtext)
|
||||
if not split_by_strings then
|
||||
error(err)
|
||||
end
|
||||
local struct = {global = {}}
|
||||
local block = "global"
|
||||
local last_string_key = nil
|
||||
local err
|
||||
for k,v in pairs(split_by_strings) do
|
||||
if not split_by_strings then error(err) end
|
||||
local full_split = {{}}
|
||||
local current_line = full_split[1]
|
||||
-- tokenizer
|
||||
for _,v in pairs(split_by_strings) do
|
||||
v = v:match("^[ \t]*(.*)[ \t]*$")
|
||||
if (not (v == "")) then
|
||||
if not v:match("^\".*\"$") then
|
||||
v:gsub("[^\n]*",function(line)
|
||||
-- Nothing
|
||||
if line:match("^%s*$") then
|
||||
return
|
||||
v:gsub("[^ \t]+",function(text)
|
||||
while text:match("\n") do
|
||||
local before,after = text:match("([^\n]*)\n(.*)")
|
||||
if before ~= "" then
|
||||
table.insert(current_line,before)
|
||||
end
|
||||
-- Namespace block
|
||||
if line:match("^%s*%[[^%]]-%]%s*$") then
|
||||
block = line:match("%[([^%]]-)%]")
|
||||
struct[block] = {}
|
||||
return
|
||||
if #current_line > 0 then
|
||||
table.insert(full_split,{})
|
||||
current_line = full_split[#full_split]
|
||||
end
|
||||
-- String/Multiline string assignment
|
||||
if line:match("^%s*[^=]-%s*=%s*$") then
|
||||
last_string_key = line:match("^%s*([^=]-)%s*=%s*$")
|
||||
return
|
||||
text = after
|
||||
end
|
||||
-- Number/boolean assignment
|
||||
local key,value = line:match("^%s*([^=]-)%s*=%s*(.-)%s*$")
|
||||
-- number
|
||||
if value:match("^[%d%.]*$") then
|
||||
value = tonumber(value)
|
||||
-- bool
|
||||
elseif (value:lower() == "yes") or (value:lower() == "no") then
|
||||
value = (value:lower() == "yes")
|
||||
if text ~= "" then
|
||||
table.insert(current_line,text)
|
||||
end
|
||||
struct[block][key] = value
|
||||
end)
|
||||
else
|
||||
struct[block][last_string_key] = v:sub(2,-2)
|
||||
table.insert(current_line,v)
|
||||
end
|
||||
end
|
||||
end
|
||||
table.remove(full_split,#full_split)
|
||||
local struct = {global = {}}
|
||||
local block = "global"
|
||||
-- parser
|
||||
for _,line in pairs(full_split) do
|
||||
if line[1] and line[1]:match("^%[[^%]]+%]$") then -- block
|
||||
block = line[1]:match("^%[([^%]]+)%]$")
|
||||
struct[block] = {}
|
||||
elseif #line == 3 then -- assignment
|
||||
if (line[3]:sub(1,1):match("['\"]")) -- string
|
||||
and (line[3]:sub(-1,-1) == line[3]:sub(1,1)) then
|
||||
struct[block][quotestrip(line[1])] = quotestrip(line[3])
|
||||
elseif line[3]:match("^%d+$") then -- number
|
||||
struct[block][quotestrip(line[1])] = tonumber(line[3])
|
||||
elseif (line[3] == "true") or (line[3] == "false") then -- boolean
|
||||
struct[block][quotestrip(line[1])] = (line[3] == "true")
|
||||
else
|
||||
error("Invalid assignment expression: "..line[3])
|
||||
end
|
||||
else -- invalid
|
||||
local textline = ""
|
||||
for _,v in pairs(line) do
|
||||
textline = textline..v.." "
|
||||
end
|
||||
error("Invalid config expression: "..textline:sub(1,-2))
|
||||
end
|
||||
end
|
||||
return struct
|
||||
|
|
|
@ -5,11 +5,82 @@
|
|||
-- Reno desktop is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License along with Reno desktop. If not, see <https://www.gnu.org/licenses/>.
|
||||
-- XFCE style autostart system
|
||||
-- XFCE style autostart system with a system to automatically kill children just to fuck over Steam. (now with SMЯT targeting software package!)
|
||||
local awful = require("awful")
|
||||
local gears = require("gears")
|
||||
local gfs = gears.filesystem
|
||||
local menu_utils = require("menubar.utils")
|
||||
local hide_ids = {}
|
||||
local related_ids = {}
|
||||
local settings = config.autostart
|
||||
local stop_checking = false
|
||||
-- I know this is linux specific, blame Steam for creating a triple-forking launcher with no startup id.
|
||||
-- I love the fact that valve is supportive of linux and thinks it's the future of gaming and all that
|
||||
-- but you could've just done the due diligence and, yk, maybe research how things work with XDG?
|
||||
-- P.S. if you know how to make this function work in similar vein on BSD, feel free to contribute
|
||||
local function is_child_of(pid,related)
|
||||
related = related or pid
|
||||
local ppidfile = io.open("/proc/"..tostring(pid).."/status","rb")
|
||||
if not ppidfile then return false end
|
||||
local ppid = ppidfile:read("*a"):match("PPid:%s*(%d+)")
|
||||
ppidfile:close()
|
||||
if (not ppid) or (ppid == "1") then return false end
|
||||
if hide_ids[tonumber(ppid)] then
|
||||
related_ids[related] = tonumber(ppid)
|
||||
return true
|
||||
else
|
||||
return is_child_of(ppid,related)
|
||||
end
|
||||
end
|
||||
-- Play whack-a-mole with the clients that match ids to hide
|
||||
-- NO MORE MR NICE GUY, until the user EXPLICITLY activates the client,
|
||||
-- it's being hidden.
|
||||
local callback = function(c)
|
||||
if not settings.minimize_enable then return end
|
||||
if stop_checking then return end
|
||||
gears.timer.delayed_call(function()
|
||||
local kill_later = false
|
||||
if c.pid and hide_ids[c.pid] then
|
||||
kill_later = true
|
||||
end
|
||||
if c.startup_id and hide_ids[c.startup_id] then
|
||||
kill_later = true
|
||||
end
|
||||
if c.pid and is_child_of(c.pid) then
|
||||
kill_later = true
|
||||
end
|
||||
if kill_later then
|
||||
c.minimized = true
|
||||
end
|
||||
end)
|
||||
end
|
||||
client.connect_signal("focus",callback)
|
||||
client.connect_signal("manage",callback)
|
||||
-- if the client has been mouse pressed we no longer hide it or any of its siblings - user needs the client to be active.
|
||||
client.connect_signal("request::activate",function(c,reason)
|
||||
if (reason ~= "mouse_click") and (reason ~= "tasklist") then
|
||||
return
|
||||
end
|
||||
if c.pid then
|
||||
hide_ids[c.pid] = nil
|
||||
if related_ids[c.pid] then
|
||||
hide_ids[related_ids[c.pid]] = nil
|
||||
end
|
||||
end
|
||||
if c.startup_id then
|
||||
hide_ids[c.startup_id] = nil
|
||||
end
|
||||
end)
|
||||
-- this ain't happy hour - stop hitting everything in sight.
|
||||
gears.timer {
|
||||
timeout = settings.minimize_timeout or 30,
|
||||
autostart = true,
|
||||
single_shot = true,
|
||||
callback = function()
|
||||
stop_checking = true
|
||||
hide_ids = {}
|
||||
end
|
||||
}
|
||||
local stdir = os.getenv("XDG_RUNTIME_DIR").."/.awesome_startup/"
|
||||
gfs.make_directories(stdir)
|
||||
awful.spawn.with_line_callback("find "..gfs.get_xdg_config_home().."autostart/ -name *.desktop",{
|
||||
|
@ -17,8 +88,16 @@ awful.spawn.with_line_callback("find "..gfs.get_xdg_config_home().."autostart/ -
|
|||
local data = menu_utils.parse_desktop_file(line)
|
||||
if (data.RunHook == "0") or (data.RunHook == nil) then
|
||||
if not gfs.file_readable(stdir..line:match("[^/]*$")) then
|
||||
io.open(stdir..line:match("[^/]*$"),"w"):close()
|
||||
awful.spawn(data.Exec:gsub("%%%w",""))
|
||||
local npid,nsnid = awful.spawn(data.Exec:gsub("%%%w",""))
|
||||
io.open(stdir..line:match("[^/]*$"),"w"):write(npid):close()
|
||||
if data.Hidden then
|
||||
if npid then
|
||||
hide_ids[npid] = true
|
||||
end
|
||||
if nsnid then
|
||||
hide_ids[nsnid] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,10 +1,3 @@
|
|||
-- This file is part of Reno desktop.
|
||||
--
|
||||
-- Reno desktop is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
--
|
||||
-- Reno desktop is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License along with Reno desktop. If not, see <https://www.gnu.org/licenses/>.
|
||||
local awful = require("awful")
|
||||
local gears = require("gears")
|
||||
awful.rules.rules = gears.table.join(awful.rules.rules, {
|
||||
|
@ -16,14 +9,10 @@ awful.rules.rules = gears.table.join(awful.rules.rules, {
|
|||
}},
|
||||
properties = {inhibit_compositor = true},
|
||||
},
|
||||
{ rule_any = { class = {
|
||||
"thunderbird"
|
||||
}},
|
||||
properties = {callback = function(c)
|
||||
gears.timer.delayed_call(function()
|
||||
c.minimized = true
|
||||
end)
|
||||
end}
|
||||
{ rule = { name = "notificationtoasts.*" },
|
||||
properties = {
|
||||
focusable = false
|
||||
}
|
||||
},
|
||||
{ rule = { fullscreen = true },
|
||||
properties = {
|
||||
|
|
2
rc.lua
2
rc.lua
|
@ -18,11 +18,11 @@ require("modules.collect_garbage")
|
|||
require("modules.global")
|
||||
require("modules.powermanX")
|
||||
require("modules.base")
|
||||
require("modules.autostart")
|
||||
require("modules.rules_stub")
|
||||
require("modules.compositor")
|
||||
require("modules.binds")
|
||||
require("modules.xdg_data")
|
||||
require("modules.autostart")
|
||||
require("modules.static_tags")
|
||||
require("modules.tiling")
|
||||
require("modules.desktop")
|
||||
|
|
Loading…
Reference in New Issue