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>"
|
# Format: <modifier>(+<modifier>+...)+<key> = "<command or :internal.function>"
|
||||||
# "modkey" as modifier will be substituted for modkey variable in [global]
|
# "modkey" as modifier will be substituted for modkey variable in [global]
|
||||||
[keys]
|
[keys]
|
||||||
modkey+Up = ":root.client_next"
|
"modkey+Up" = ":root.client_next"
|
||||||
modkey+Down = ":root.client_previous"
|
"modkey+Down" = ":root.client_previous"
|
||||||
modkey+Control+Up = ":root.screen_next"
|
"modkey+Control+Up" = ":root.screen_next"
|
||||||
modkey+Control+Down = ":root.screen_previous"
|
"modkey+Control+Down" = ":root.screen_previous"
|
||||||
modkey+Tab = ":root.client_swap"
|
"modkey+Tab" = ":root.client_swap"
|
||||||
modkey+Return = ":root.spawn_terminal"
|
"modkey+Return" = ":root.spawn_terminal"
|
||||||
modkey+Shift+Return = ":root.spawn_browser"
|
"modkey+Shift+Return" = ":root.spawn_browser"
|
||||||
|
|
||||||
# Client keys only work if a focused client exists
|
# Client keys only work if a focused client exists
|
||||||
modkey+Shift+c = ":client.kill"
|
"modkey+Shift+c" = ":client.kill"
|
||||||
modkey+t = ":client.cycle_screen"
|
"modkey+t" = ":client.cycle_screen"
|
||||||
modkey+o = ":client.ontop"
|
"modkey+o" = ":client.ontop"
|
||||||
modkey+b = ":client.below"
|
"modkey+b" = ":client.below"
|
||||||
modkey+f = ":client.fullscreen"
|
"modkey+f" = ":client.fullscreen"
|
||||||
modkey+n = ":client.minimize"
|
"modkey+n" = ":client.minimize"
|
||||||
modkey+m = ":client.maximize"
|
"modkey+m" = ":client.maximize"
|
||||||
|
|
||||||
]]
|
]]
|
||||||
for k,v in pairs(parsers.conf(data)) do
|
for k,v in pairs(parsers.conf(data)) do
|
||||||
print("Block: ["..k.."]")
|
print("Block: ["..k.."]")
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
local parsers = {}
|
local parsers = {}
|
||||||
|
|
||||||
local function split_strings(text)
|
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 = {}
|
local split = {}
|
||||||
while text:find("\"") do
|
while text:find("\"") do
|
||||||
local strstart = text:find("\"")
|
local strstart = text:find("\"")
|
||||||
|
@ -86,48 +86,74 @@ parsers.yaml_pseudo = function(cfgtext)
|
||||||
return struct
|
return struct
|
||||||
end
|
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)
|
parsers.conf = function(cfgtext)
|
||||||
-- Conf style parser (not exactly TOML)
|
-- Conf style parser (not exactly TOML)
|
||||||
cfgtext = cfgtext:gsub("#[^\n]*","")
|
cfgtext = cfgtext:gsub("#[^\n]*","")
|
||||||
local split_by_strings,err = split_strings(cfgtext)
|
local split_by_strings,err = split_strings(cfgtext)
|
||||||
if not split_by_strings then
|
if not split_by_strings then error(err) end
|
||||||
error(err)
|
local full_split = {{}}
|
||||||
end
|
local current_line = full_split[1]
|
||||||
local struct = {global = {}}
|
-- tokenizer
|
||||||
local block = "global"
|
for _,v in pairs(split_by_strings) do
|
||||||
local last_string_key = nil
|
v = v:match("^[ \t]*(.*)[ \t]*$")
|
||||||
local err
|
if (not (v == "")) then
|
||||||
for k,v in pairs(split_by_strings) do
|
|
||||||
if not v:match("^\".*\"$") then
|
if not v:match("^\".*\"$") then
|
||||||
v:gsub("[^\n]*",function(line)
|
v:gsub("[^ \t]+",function(text)
|
||||||
-- Nothing
|
while text:match("\n") do
|
||||||
if line:match("^%s*$") then
|
local before,after = text:match("([^\n]*)\n(.*)")
|
||||||
return
|
if before ~= "" then
|
||||||
|
table.insert(current_line,before)
|
||||||
end
|
end
|
||||||
-- Namespace block
|
if #current_line > 0 then
|
||||||
if line:match("^%s*%[[^%]]-%]%s*$") then
|
table.insert(full_split,{})
|
||||||
block = line:match("%[([^%]]-)%]")
|
current_line = full_split[#full_split]
|
||||||
struct[block] = {}
|
|
||||||
return
|
|
||||||
end
|
end
|
||||||
-- String/Multiline string assignment
|
text = after
|
||||||
if line:match("^%s*[^=]-%s*=%s*$") then
|
|
||||||
last_string_key = line:match("^%s*([^=]-)%s*=%s*$")
|
|
||||||
return
|
|
||||||
end
|
end
|
||||||
-- Number/boolean assignment
|
if text ~= "" then
|
||||||
local key,value = line:match("^%s*([^=]-)%s*=%s*(.-)%s*$")
|
table.insert(current_line,text)
|
||||||
-- number
|
|
||||||
if value:match("^[%d%.]*$") then
|
|
||||||
value = tonumber(value)
|
|
||||||
-- bool
|
|
||||||
elseif (value:lower() == "yes") or (value:lower() == "no") then
|
|
||||||
value = (value:lower() == "yes")
|
|
||||||
end
|
end
|
||||||
struct[block][key] = value
|
|
||||||
end)
|
end)
|
||||||
else
|
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
|
||||||
end
|
end
|
||||||
return struct
|
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.
|
-- 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/>.
|
-- 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 awful = require("awful")
|
||||||
local gears = require("gears")
|
local gears = require("gears")
|
||||||
local gfs = gears.filesystem
|
local gfs = gears.filesystem
|
||||||
local menu_utils = require("menubar.utils")
|
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/"
|
local stdir = os.getenv("XDG_RUNTIME_DIR").."/.awesome_startup/"
|
||||||
gfs.make_directories(stdir)
|
gfs.make_directories(stdir)
|
||||||
awful.spawn.with_line_callback("find "..gfs.get_xdg_config_home().."autostart/ -name *.desktop",{
|
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)
|
local data = menu_utils.parse_desktop_file(line)
|
||||||
if (data.RunHook == "0") or (data.RunHook == nil) then
|
if (data.RunHook == "0") or (data.RunHook == nil) then
|
||||||
if not gfs.file_readable(stdir..line:match("[^/]*$")) then
|
if not gfs.file_readable(stdir..line:match("[^/]*$")) then
|
||||||
io.open(stdir..line:match("[^/]*$"),"w"):close()
|
local npid,nsnid = awful.spawn(data.Exec:gsub("%%%w",""))
|
||||||
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
|
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 awful = require("awful")
|
||||||
local gears = require("gears")
|
local gears = require("gears")
|
||||||
awful.rules.rules = gears.table.join(awful.rules.rules, {
|
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},
|
properties = {inhibit_compositor = true},
|
||||||
},
|
},
|
||||||
{ rule_any = { class = {
|
{ rule = { name = "notificationtoasts.*" },
|
||||||
"thunderbird"
|
properties = {
|
||||||
}},
|
focusable = false
|
||||||
properties = {callback = function(c)
|
}
|
||||||
gears.timer.delayed_call(function()
|
|
||||||
c.minimized = true
|
|
||||||
end)
|
|
||||||
end}
|
|
||||||
},
|
},
|
||||||
{ rule = { fullscreen = true },
|
{ rule = { fullscreen = true },
|
||||||
properties = {
|
properties = {
|
||||||
|
|
2
rc.lua
2
rc.lua
|
@ -18,11 +18,11 @@ require("modules.collect_garbage")
|
||||||
require("modules.global")
|
require("modules.global")
|
||||||
require("modules.powermanX")
|
require("modules.powermanX")
|
||||||
require("modules.base")
|
require("modules.base")
|
||||||
|
require("modules.autostart")
|
||||||
require("modules.rules_stub")
|
require("modules.rules_stub")
|
||||||
require("modules.compositor")
|
require("modules.compositor")
|
||||||
require("modules.binds")
|
require("modules.binds")
|
||||||
require("modules.xdg_data")
|
require("modules.xdg_data")
|
||||||
require("modules.autostart")
|
|
||||||
require("modules.static_tags")
|
require("modules.static_tags")
|
||||||
require("modules.tiling")
|
require("modules.tiling")
|
||||||
require("modules.desktop")
|
require("modules.desktop")
|
||||||
|
|
Loading…
Reference in New Issue