add new calendar widget with ics file support, fix some bugs and added some game rules so steam games fullscreen isn't as annoying
This commit is contained in:
@@ -17,7 +17,6 @@ Gtk.IconTheme.set_custom_theme(gtk_theme, User_config.icon_theme)
|
||||
---@param app Gio.AppInfo
|
||||
---@return string path
|
||||
function Get_gicon_path(app)
|
||||
if not app then return "" end
|
||||
local icon_info = gtk_theme:lookup_by_gicon(app, 64, 0)
|
||||
if icon_info then
|
||||
local path = icon_info:get_filename()
|
||||
@@ -37,12 +36,12 @@ function Get_icon(class, name)
|
||||
name = string.lower(name or "")
|
||||
for _, app in ipairs(app_list) do
|
||||
local desktop_app_info = Gio.DesktopAppInfo.new(app_info.get_id(app))
|
||||
local icon_string = Gio.DesktopAppInfo.get_string(desktop_app_info, "Name")
|
||||
local icon_string = Gio.DesktopAppInfo.get_string(desktop_app_info, "Icon")
|
||||
if icon_string then
|
||||
icon_string = string.lower(icon_string)
|
||||
if icon_string:match(class) or class:match(icon_string) then
|
||||
return Get_gicon_path(app_info.get_icon(app))
|
||||
elseif (icon_string == name) or icon_string:match(name) or name:match(icon_string) then
|
||||
elseif icon_string:match(name) or name:match(icon_string) then
|
||||
return Get_gicon_path(app_info.get_icon(app))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,7 +3,7 @@ local awful = require("awful")
|
||||
BACKLIGHT_MAX_BRIGHTNESS = 0
|
||||
BACKLIGHT_SEPS = 0
|
||||
awful.spawn.easy_async_with_shell(
|
||||
"xfpm-power-backlight-helper --get-max-brightness",
|
||||
"pkexec xfpm-power-backlight-helper --get-max-brightness",
|
||||
function(stdout)
|
||||
BACKLIGHT_MAX_BRIGHTNESS = tonumber(stdout)
|
||||
BACKLIGHT_SEPS = BACKLIGHT_MAX_BRIGHTNESS / 100
|
||||
@@ -15,7 +15,7 @@ awesome.connect_signal(
|
||||
"brightness::update",
|
||||
function()
|
||||
awful.spawn.easy_async_with_shell(
|
||||
"xfpm-power-backlight-helper --get-brightness",
|
||||
"pkexec xfpm-power-backlight-helper --get-brightness",
|
||||
function(value)
|
||||
awesome.emit_signal("brightness::get", math.floor((tonumber(value) - 1) / (BACKLIGHT_MAX_BRIGHTNESS - 1) * 100))
|
||||
awesome.emit_signal("brightness::rerun")
|
||||
@@ -23,5 +23,3 @@ awesome.connect_signal(
|
||||
)
|
||||
end
|
||||
)
|
||||
|
||||
awesome.emit_signal("brightness::update")
|
||||
|
||||
@@ -5,4 +5,4 @@ require("src.tools.helpers.ram")
|
||||
require("src.tools.helpers.gpu_usage")
|
||||
require("src.tools.helpers.gpu_temp")
|
||||
require("src.tools.helpers.audio")
|
||||
require("src.tools.helpers.backlight")
|
||||
--require("src.tools.helpers.backlight")
|
||||
|
||||
332
awesome/src/tools/ical_parser.lua
Normal file
332
awesome/src/tools/ical_parser.lua
Normal file
@@ -0,0 +1,332 @@
|
||||
local ical = {}
|
||||
ical.VCALENDAR = {}
|
||||
ical._private = {}
|
||||
ical._private.parser = {}
|
||||
|
||||
--[[
|
||||
The structure of ical looks like this:
|
||||
ical = {
|
||||
VCALENDAR = {
|
||||
PRODID = "...",
|
||||
VERSION = "...",
|
||||
CALSCALE = "...",
|
||||
METHOD = "...",
|
||||
X-WR-CALNAME = "...",
|
||||
X-WR-CALDESC = "...",
|
||||
X-WR-TIMEZONE = "...",
|
||||
VTIMEZONE = {
|
||||
TZID = "...",
|
||||
TZURL = "...",
|
||||
X-LIC-LOCATION = "...",
|
||||
STANDARD = {
|
||||
TZOFFSETFROM = "...",
|
||||
TZOFFSETTO = "...",
|
||||
TZNAME = "...",
|
||||
DTSTART = "...",
|
||||
TZRDATE = "...",
|
||||
TZRULE = "...",
|
||||
TZUNTIL = "...",
|
||||
TZPERIOD = "...",
|
||||
},
|
||||
DAYLIGHT = {
|
||||
TZOFFSETFROM = "...",
|
||||
TZOFFSETTO = "...",
|
||||
TZNAME = "...",
|
||||
DTSTART = "...",
|
||||
TZRDATE = "...",
|
||||
TZRULE = "...",
|
||||
TZUNTIL = "...",
|
||||
TZPERIOD = "...",
|
||||
},
|
||||
},
|
||||
VEVENT = {
|
||||
UID = "...",
|
||||
DTSTAMP = "...",
|
||||
DTSTART = "...",
|
||||
DTEND = "...",
|
||||
SUMMARY = "...",
|
||||
DESCRIPTION = "...",
|
||||
LOCATION = "...",
|
||||
RRULE = "...",
|
||||
RDATE = "...",
|
||||
EXDATE = "...",
|
||||
CLASS = "...",
|
||||
STATUS = "...",
|
||||
TRANSP = "...",
|
||||
SEQUENCE = "...",
|
||||
ORGANIZER = "...",
|
||||
ATTENDEE = "...",
|
||||
CATEGORIES = "...",
|
||||
PRIORITY = "...",
|
||||
URL = "...",
|
||||
UID = "...",
|
||||
DTSTAMP = "...",
|
||||
]]
|
||||
|
||||
---Takes a path to an .ical file then parses it into a lua table and returns it
|
||||
---@param path string Path to the .ical file
|
||||
---@return table | nil calendar New calendar table or nil on error
|
||||
function ical.new(path)
|
||||
local handler = io.open(path, "r")
|
||||
if not handler then return end
|
||||
|
||||
-- Check if the line is a BEGIN:VCALENDAR
|
||||
local v, k = handler:read("l"):match("([A-Z]+):([A-Z]+)")
|
||||
|
||||
if v:match("BEGIN") and k:match("VCALENDAR") then
|
||||
table.insert(ical.VCALENDAR, ical._private.parser.VCALENDAR(handler))
|
||||
return ical
|
||||
end
|
||||
return ical
|
||||
end
|
||||
|
||||
function ical._private.parser.VEVENT(handler)
|
||||
local VEVENT = {}
|
||||
|
||||
while true do
|
||||
local line = handler:read("l")
|
||||
|
||||
if not line or line:match("END:VEVENT") then
|
||||
break
|
||||
end
|
||||
|
||||
local v, k = line:match("(.*):(.*)")
|
||||
if v:match("CREATED") then
|
||||
VEVENT.CREATED = ical._private.parser.to_datetime(k)
|
||||
elseif v:match("LAST-MODIFIED") then
|
||||
VEVENT.LAST_MODIFIED = ical._private.parser.to_datetime(k)
|
||||
elseif v:match("DTSTAMP") then
|
||||
VEVENT.DTSTAMP = ical._private.parser.to_datetime(k)
|
||||
elseif v:match("UID") then
|
||||
VEVENT.UID = k
|
||||
elseif v:match("SUMMARY") then
|
||||
VEVENT.SUMMARY = k
|
||||
elseif v:match("RRULE") then
|
||||
VEVENT.RRULE = {
|
||||
FREQ = k:match("FREQ=([A-Z]+)"),
|
||||
UNTIL = ical._private.parser.to_datetime(k:match("UNTIL=([TZ0-9]+)")),
|
||||
WKST = k:match("WKST=([A-Z]+)"),
|
||||
COUNT = k:match("COUNT=([0-9]+)"),
|
||||
INTERVAL = k:match("INTERVAL=([0-9]+)")
|
||||
}
|
||||
elseif v:match("DTSTART") then
|
||||
VEVENT.DTSTART = {
|
||||
DTSTART = ical._private.parser.to_datetime(k),
|
||||
TZID = v:match("TZID=([a-zA-Z-\\/]+)"),
|
||||
VALUE = v:match("VALUE=([A-Z]+)")
|
||||
}
|
||||
elseif v:match("DTEND") then
|
||||
VEVENT.DTEND = {
|
||||
DTEND = ical._private.parser.to_datetime(k),
|
||||
TZID = v:match("TZID=([a-zA-Z-\\/]+)"),
|
||||
VALUE = v:match("VALUE=([A-Z]+)")
|
||||
}
|
||||
elseif v:match("TRANSP") then
|
||||
VEVENT.TRANSP = k
|
||||
elseif v:match("LOCATION") then
|
||||
VEVENT.LOCATION = k
|
||||
elseif v:match("DESCRIPTION") then
|
||||
VEVENT.DESCRIPTION = k
|
||||
elseif v:match("URL") then
|
||||
VEVENT.URL = {
|
||||
URL = k,
|
||||
VALUE = v:match("VALUE=([A-Z]+)")
|
||||
}
|
||||
elseif v:match("BEGIN") then
|
||||
if k:match("VALARM") then
|
||||
VEVENT.VALARM = ical._private.parser.VALARM(handler)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--VEVENT.duration = VEVENT.DTSTART.DTSTART - VEVENT.DTEND.DTEND
|
||||
|
||||
return VEVENT
|
||||
end
|
||||
|
||||
function ical._private.parser.alarm_to_time(alarm)
|
||||
if not alarm then return end
|
||||
--Parse alarm into a time depending on its value. The value will be -PT15M where - mean before and with no leading - it means after. PT can be ignored and 15 is the time M then the unit where M is minute, H is out etc
|
||||
local time = alarm:match("([-]?[0-9]+)[A-Z]")
|
||||
local unit = alarm:match("[-]?[A-Z][A-Z][0-9]+([A-Z]*)")
|
||||
|
||||
return time .. unit
|
||||
end
|
||||
|
||||
function ical._private.parser.VALARM(handler)
|
||||
local VALARM = {}
|
||||
|
||||
while true do
|
||||
local line = handler:read("l")
|
||||
|
||||
if not line or line:match("END:VALARM") then
|
||||
break
|
||||
end
|
||||
|
||||
local v, k = line:match("(.*):(.*)")
|
||||
if v:match("ACTION") then
|
||||
VALARM.ACTION = k
|
||||
elseif v:match("TRIGGER;VALUE=DURATION") then
|
||||
VALARM.TRIGGER = {
|
||||
VALUE = v:match("VALUE=(.*):"),
|
||||
TRIGGER = ical._private.parser.alarm_to_time(k)
|
||||
}
|
||||
elseif v:match("DESCRIPTION") then
|
||||
VALARM.DESCRIPTION = k
|
||||
end
|
||||
end
|
||||
|
||||
return VALARM
|
||||
end
|
||||
|
||||
function ical._private.parser.VCALENDAR(handler)
|
||||
local VCALENDAR = {}
|
||||
VCALENDAR.VEVENT = {}
|
||||
VCALENDAR.VTIMEZONE = {}
|
||||
|
||||
while true do
|
||||
local line = handler:read("l")
|
||||
|
||||
if not line or line:match("END:VCALENDAR") then
|
||||
break
|
||||
end
|
||||
|
||||
local v, k = line:match("(.*):(.*)")
|
||||
if v and k then
|
||||
if v:match("PRODID") then
|
||||
VCALENDAR.PRODID = k
|
||||
elseif v:match("VERSION") then
|
||||
VCALENDAR.VERSION = k
|
||||
elseif v:match("BEGIN") then
|
||||
if k:match("VTIMEZONE") then
|
||||
VCALENDAR.VTIMEZONE = ical._private.parser.VTIMEZONE(handler)
|
||||
elseif k:match("VEVENT") then
|
||||
table.insert(VCALENDAR.VEVENT, ical._private.parser.VEVENT(handler))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
handler:close()
|
||||
return VCALENDAR
|
||||
end
|
||||
|
||||
function ical._private.parser.VTIMEZONE(handler)
|
||||
local VTIMEZONE = {}
|
||||
|
||||
while true do
|
||||
local line = handler:read("l")
|
||||
|
||||
if not line or line:match("END:VTIMEZONE") then
|
||||
break
|
||||
end
|
||||
|
||||
local v, k = line:match("(.*):(.*)")
|
||||
if v:match("TZID") then
|
||||
VTIMEZONE.TZID = k
|
||||
end
|
||||
if v:match("BEGIN") then
|
||||
if k:match("DAYLIGHT") then
|
||||
VTIMEZONE.DAYLIGHT = ical._private.parser.DAYLIGHT(handler)
|
||||
elseif k:match("STANDARD") then
|
||||
VTIMEZONE.STANDARD = ical._private.parser.STANDARD(handler)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return VTIMEZONE
|
||||
end
|
||||
|
||||
function ical._private.parser.DAYLIGHT(handler)
|
||||
local DAYLIGHT = {}
|
||||
|
||||
while true do
|
||||
local line = handler:read("l")
|
||||
|
||||
if not line or line:match("END:DAYLIGHT") then
|
||||
break
|
||||
end
|
||||
|
||||
local v, k = line:match("(.*):(.*)")
|
||||
if v:match("TZOFFSETFROM") then
|
||||
DAYLIGHT.TZOFFSETFROM = ical._private.parser.offset(k)
|
||||
elseif v:match("TZOFFSETTO") then
|
||||
DAYLIGHT.TZOFFSETTO = ical._private.parser.offset(k)
|
||||
elseif v:match("TZNAME") then
|
||||
DAYLIGHT.TZNAME = k
|
||||
elseif v:match("DTSTART") then
|
||||
DAYLIGHT.DTSTART = ical._private.parser.to_datetime(k)
|
||||
elseif v:match("RRULE") then
|
||||
DAYLIGHT.RRULE = {
|
||||
FREQ = k:match("FREQ=([A-Z]+)"),
|
||||
BYDAY = k:match("BYDAY=([%+%-0-9A-Z,]+)"),
|
||||
BYMONTH = k:match("BYMONTH=([0-9]+)")
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
return DAYLIGHT
|
||||
end
|
||||
|
||||
---Parses the STANDARD property into a table
|
||||
---@param handler table
|
||||
---@return table STANDARD The STANDARD property as a table
|
||||
function ical._private.parser.STANDARD(handler)
|
||||
local STANDARD = {}
|
||||
|
||||
-- Read each line until END:STANDARD is read
|
||||
while true do
|
||||
local line = handler:read("l")
|
||||
|
||||
if not line or line:match("END:STANDARD") then
|
||||
break
|
||||
end
|
||||
|
||||
-- Break down each line into the property:value
|
||||
local v, k = line:match("(.*):(.*)")
|
||||
if v:match("TZOFFSETFROM") then
|
||||
STANDARD.TZOFFSETFROM = ical._private.parser.offset(k)
|
||||
elseif v:match("TZOFFSETTO") then
|
||||
STANDARD.TZOFFSETTO = ical._private.parser.offset(k)
|
||||
elseif v:match("TZNAME") then
|
||||
STANDARD.TZNAME = k
|
||||
elseif v:match("DTSTART") then
|
||||
STANDARD.DTSTART = ical._private.parser.to_datetime(k)
|
||||
elseif v:match("RRULE") then
|
||||
STANDARD.RRULE = {
|
||||
FREQ = k:match("FREQ=([A-Z]+)"),
|
||||
BYDAY = k:match("BYDAY=([%+%-0-9A-Z,]+)"),
|
||||
BYMONTH = k:match("BYMONTH=([0-9]+)")
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
return STANDARD
|
||||
end
|
||||
|
||||
---Parse the ical date time format into an os.time integer and the utc
|
||||
---@param datetime string The datetime from the ical
|
||||
---@return date|nil time Parsed os.time()
|
||||
---@return unknown|nil utc UTC identifier
|
||||
function ical._private.parser.to_datetime(datetime)
|
||||
if not datetime then return end
|
||||
local dt, utc = {}, nil
|
||||
|
||||
dt.year, dt.month, dt.day = datetime:match("^(%d%d%d%d)(%d%d)(%d%d)")
|
||||
dt.hour, dt.min, dt.sec, utc = datetime:match("T(%d%d)(%d%d)(%d%d)(Z?)")
|
||||
|
||||
if (dt.hour == nil) or (dt.min == nil) or (dt.sec == nil) then
|
||||
dt.hour, dt.min, dt.sec, utc = 0, 0, 0, nil
|
||||
end
|
||||
|
||||
for k, v in pairs(dt) do dt[k] = tonumber(v) end
|
||||
return dt, utc
|
||||
end
|
||||
|
||||
function ical._private.parser.offset(offset)
|
||||
local s, h, m = offset:match("([+-])(%d%d)(%d%d)")
|
||||
if s == "+" then s = 1 else s = -1 end
|
||||
return s * (tonumber(h) * 3600 + tonumber(m) * 60)
|
||||
end
|
||||
|
||||
return ical
|
||||
Reference in New Issue
Block a user