more compliant conf parser and smart autominimization of apps on boot

This commit is contained in:
Yessiest 2023-07-03 20:53:52 +04:00
parent 08c4d52480
commit fc811359ae
5 changed files with 163 additions and 70 deletions

View File

@ -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.."]")

View File

@ -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

View File

@ -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

View File

@ -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
View File

@ -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")