local awful = require "awful" local phosphor = require "assets.phosphor" local qbind = require "quarrel.bind" local qmarkup = require "quarrel.markup" local qui = require "quarrel.ui" local qvars = require "quarrel.vars" local wibox = require "wibox" local weekday_map = { 7, 1, 2, 3, 4, 5, 6 } local calendar = wibox.widget(qui.styled { widget = wibox.container.background, { widget = wibox.container.margin, margins = qvars.big_padding, { { { widget = wibox.container.place, qui.icon { icon = phosphor.caret_left_bold, }, }, { widget = wibox.container.place, { widget = wibox.widget.textbox, text = "January 2024", }, }, { widget = wibox.container.place, qui.icon { icon = phosphor.caret_right_bold, }, }, layout = wibox.layout.align.horizontal, expand = "outside", }, { layout = wibox.layout.grid, forced_num_rows = 7, forced_num_cols = 7, spacing = qvars.padding, id = "grid", }, layout = wibox.layout.fixed.vertical, spacing = qvars.big_padding, }, }, }) -- Logic heavily inspired by https://github.com/Sinomor/dotfiles/blob/e409f9a84bf40daf1e39c0179ec749232ed827c9/home/.config/awesome/ui/control/moment/calendar.lua#L134-L173 function calendar:compute_grid(year, month) local calendar_table = { {}, {}, {}, {}, {}, {} } local current = os.date("*t", os.time()) local first_day = os.date("*t", os.time { year = year, month = month, day = 1 }) local last_day = os.date("*t", os.time { year = year, month = month + 1, day = 0 }) local days = last_day.day local prev_days = os.date("*t", os.time { year = year, month = month, day = 0 }) local prev_offset = weekday_map[first_day.wday] - 1 local prev_month = month - 1 == -1 and 12 or month - 1 local prev_year = prev_month == 12 and year - 1 or year if prev_offset ~= -1 then for offset = prev_offset, 1, -1 do local day = prev_days.day - offset + 1 table.insert( calendar_table[1], { day, day == current.day and prev_month == current.month and prev_year == current.year, false } ) end end do local row = 1 local weekday = weekday_map[first_day.wday] for day = 1, days do table.insert( calendar_table[row], { day, day == current.day and month == current.month and year == current.year, true } ) if weekday == 7 then row = row + 1 weekday = 1 else weekday = weekday + 1 end end local next_month = month + 1 == 13 and 1 or month + 1 local next_year = next_month == 1 and year + 1 or year for day = 1, 42 - prev_offset - days do table.insert( calendar_table[row], { day, day == current.day and next_month + 1 == current.month and next_year == current.year, false } ) if weekday == 7 then row = row + 1 weekday = 1 else weekday = weekday + 1 end end end for i, row in ipairs(calendar_table) do for j, col in ipairs(row) do local widget = self:get_children_by_id("grid")[1]:get_widgets_at(i + 1, j)[1] widget.widget.widget.text = col[1] if col[2] then widget.bg = qvars.colors.yellow widget.fg = qvars.colors.bg else widget.bg = qvars.colors.bg widget.fg = col[3] and qvars.colors.fg or qvars.colors.dim.fg end end end end local cells = {} local function cell(content) local widget = wibox.widget { widget = wibox.container.background, shape = qvars.shape, { widget = wibox.container.place, forced_height = qvars.char_height * 1.5, forced_width = qvars.char_height * 1.5, { widget = wibox.widget.textbox, markup = content, }, }, } table.insert(cells, widget) end cell "Mo" cell "Tu" cell "We" cell "Th" cell "Fr" cell(qmarkup("Sa", { bold = true })) cell(qmarkup("Su", { bold = true })) for _ = 1, 42 do cell() end calendar:get_children_by_id("grid")[1]:add(table.unpack(cells)) calendar:compute_grid(2024, 1) return calendar