Browse Source

more compliant conf parser and smart autominimization of apps on boot

master
Yessiest 10 months ago
parent
commit
fc811359ae
  1. 29
      libs/parser_test.lua
  2. 98
      libs/parsers.lua
  3. 85
      modules/autostart.lua
  4. 19
      modules/rules_stub.lua
  5. 2
      rc.lua

29
libs/parser_test.lua

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

98
libs/parsers.lua

@ -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)
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("[^ \t]+",function(text)
while text:match("\n") do
local before,after = text:match("([^\n]*)\n(.*)")
if before ~= "" then
table.insert(current_line,before)
end
if #current_line > 0 then
table.insert(full_split,{})
current_line = full_split[#full_split]
end
text = after
end
if text ~= "" then
table.insert(current_line,text)
end
end)
else
table.insert(current_line,v)
end
end
end
table.remove(full_split,#full_split)
local struct = {global = {}}
local block = "global"
local last_string_key = nil
local err
for k,v in pairs(split_by_strings) do
if not v:match("^\".*\"$") then
v:gsub("[^\n]*",function(line)
-- Nothing
if line:match("^%s*$") then
return
end
-- Namespace block
if line:match("^%s*%[[^%]]-%]%s*$") then
block = line:match("%[([^%]]-)%]")
struct[block] = {}
return
end
-- String/Multiline string assignment
if line:match("^%s*[^=]-%s*=%s*$") then
last_string_key = line:match("^%s*([^=]-)%s*=%s*$")
return
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")
end
struct[block][key] = value
end)
else
struct[block][last_string_key] = v:sub(2,-2)
-- 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

85
modules/autostart.lua

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

19
modules/rules_stub.lua

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

@ -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…
Cancel
Save