aboutsummaryrefslogtreecommitdiffstats
path: root/.config/luastatus-scripts-dwm
diff options
context:
space:
mode:
Diffstat (limited to '.config/luastatus-scripts-dwm')
-rw-r--r--.config/luastatus-scripts-dwm/alsa-gauge.lua18
-rw-r--r--.config/luastatus-scripts-dwm/alsa.lua11
-rw-r--r--.config/luastatus-scripts-dwm/backlight.lua18
-rw-r--r--.config/luastatus-scripts-dwm/battery.lua53
-rw-r--r--.config/luastatus-scripts-dwm/bluetooth.lua178
-rw-r--r--.config/luastatus-scripts-dwm/cpu-temperature.lua45
-rw-r--r--.config/luastatus-scripts-dwm/cpu-usage.lua7
-rw-r--r--.config/luastatus-scripts-dwm/file-contents.lua7
-rw-r--r--.config/luastatus-scripts-dwm/fs.lua14
-rw-r--r--.config/luastatus-scripts-dwm/ip.lua20
-rw-r--r--.config/luastatus-scripts-dwm/mem-usage.lua7
-rw-r--r--.config/luastatus-scripts-dwm/mpd.lua32
-rw-r--r--.config/luastatus-scripts-dwm/network.lua72
-rw-r--r--.config/luastatus-scripts-dwm/pulse-gauge.lua18
-rw-r--r--.config/luastatus-scripts-dwm/pulse.lua10
-rw-r--r--.config/luastatus-scripts-dwm/time-date.lua58
-rw-r--r--.config/luastatus-scripts-dwm/tor.lua13
-rw-r--r--.config/luastatus-scripts-dwm/weather.lua67
-rw-r--r--.config/luastatus-scripts-dwm/xkb.lua17
19 files changed, 665 insertions, 0 deletions
diff --git a/.config/luastatus-scripts-dwm/alsa-gauge.lua b/.config/luastatus-scripts-dwm/alsa-gauge.lua
new file mode 100644
index 0000000..966e625
--- /dev/null
+++ b/.config/luastatus-scripts-dwm/alsa-gauge.lua
@@ -0,0 +1,18 @@
+local GAUGE_NCHARS = 10
+
+local function mk_gauge(level, full, empty)
+ local nfull = math.floor(level * GAUGE_NCHARS + 0.5)
+ return full:rep(nfull) .. empty:rep(GAUGE_NCHARS - nfull)
+end
+
+widget = {
+ plugin = 'alsa',
+ cb = function(t)
+ local level = (t.vol.cur - t.vol.min) / (t.vol.max - t.vol.min)
+ if t.mute then
+ return mk_gauge(level, '×', '—')
+ else
+ return mk_gauge(level, '●', '○')
+ end
+ end,
+}
diff --git a/.config/luastatus-scripts-dwm/alsa.lua b/.config/luastatus-scripts-dwm/alsa.lua
new file mode 100644
index 0000000..054a806
--- /dev/null
+++ b/.config/luastatus-scripts-dwm/alsa.lua
@@ -0,0 +1,11 @@
+widget = {
+ plugin = 'alsa',
+ cb = function(t)
+ if t.mute then
+ return '[mute]'
+ else
+ local percent = (t.vol.cur - t.vol.min) / (t.vol.max - t.vol.min) * 100
+ return string.format('[%3d%%]', math.floor(0.5 + percent))
+ end
+ end,
+}
diff --git a/.config/luastatus-scripts-dwm/backlight.lua b/.config/luastatus-scripts-dwm/backlight.lua
new file mode 100644
index 0000000..37267ed
--- /dev/null
+++ b/.config/luastatus-scripts-dwm/backlight.lua
@@ -0,0 +1,18 @@
+-- Note that this widget only shows backlight level when it changes.
+widget = luastatus.require_plugin('backlight-linux').widget{
+ cb = function(level)
+ if level ~= nil then
+ local brightness = level * 100
+
+ local icon = "󰃠"
+ if brightness < 30 then
+ icon = "󰃞"
+ elseif brightness < 70 then
+ icon = "󰃟"
+ end
+
+ io.write(level * 100)
+ return string.format(' %s %3.0f%%', icon, brightness)
+ end
+ end,
+}
diff --git a/.config/luastatus-scripts-dwm/battery.lua b/.config/luastatus-scripts-dwm/battery.lua
new file mode 100644
index 0000000..377a30e
--- /dev/null
+++ b/.config/luastatus-scripts-dwm/battery.lua
@@ -0,0 +1,53 @@
+widget = luastatus.require_plugin('battery-linux').widget{
+ period = 2,
+ cb = function(t)
+ icon = ""
+ if t.status == "Discharging" then
+ if t.capacity < 10 then
+ icon = "󰁺"
+ elseif t.capacity < 20 then
+ icon = "󰁻"
+ elseif t.capacity < 30 then
+ icon = "󰁼"
+ elseif t.capacity < 40 then
+ icon = "󰁽"
+ elseif t.capacity < 50 then
+ icon = "󰁾"
+ elseif t.capacity < 60 then
+ icon = "󰁿"
+ elseif t.capacity < 70 then
+ icon = "󰂀"
+ elseif t.capacity < 80 then
+ icon = "󰂁"
+ elseif t.capacity < 90 then
+ icon = "󰂂"
+ else
+ icon = "󰁹"
+ end
+ else
+ if t.capacity < 10 then
+ icon = "󰢜"
+ elseif t.capacity < 20 then
+ icon = "󰂆"
+ elseif t.capacity < 30 then
+ icon = "󰂇"
+ elseif t.capacity < 40 then
+ icon = "󰂈"
+ elseif t.capacity < 50 then
+ icon = "󰢝"
+ elseif t.capacity < 60 then
+ icon = "󰂉"
+ elseif t.capacity < 70 then
+ icon = "󰢞"
+ elseif t.capacity < 80 then
+ icon = "󰂊"
+ elseif t.capacity < 90 then
+ icon = "󰂋"
+ else
+ icon = "󰂅"
+ end
+ end
+
+ return string.format('%s %3d%% ', icon, t.capacity)
+ end,
+}
diff --git a/.config/luastatus-scripts-dwm/bluetooth.lua b/.config/luastatus-scripts-dwm/bluetooth.lua
new file mode 100644
index 0000000..baf4b8c
--- /dev/null
+++ b/.config/luastatus-scripts-dwm/bluetooth.lua
@@ -0,0 +1,178 @@
+-- A widget to display currently connected and paired bluetooth devices.
+-- To change output format modify reprint_devices function.
+
+separator = " "
+
+-- Object paths look like /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/somethingsomething
+function get_device_mac_address(device_object_path)
+ return device_object_path:gsub("/.*/dev_", ""):gsub("/.*", ""):gsub("_", ":")
+end
+
+-- For reference bluetoothctl devices output looks like that:
+-- Device XX:XX:XX:XX:XX:XX JBL T450BT
+-- Device YY:YY:YY:YY:YY:YY Redmi 8
+--
+-- Function returns mac addresses of all devices.
+function get_devices()
+ local devices = {}
+ local handle = io.popen(string.format("bluetoothctl devices"))
+ for line in handle:lines() do
+ table.insert(devices, string.match(line, "Device ([%x:]+)"))
+ end
+ handle:close()
+ return devices
+end
+
+function get_power_state()
+ local handle = io.popen(string.format("bluetoothctl show"))
+ local power_state = false
+ for line in handle:lines() do
+ local state = string.match(line, "^%s*PowerState:%s*(%w+)")
+ if state then
+ if state == "off" then
+ power_state = false
+ else
+ power_state = true
+ end
+ break
+ end
+ end
+ handle:close()
+
+ return power_state
+end
+
+-- For reference bluetoothctl info output looks like that:
+-- Device XX:XX:XX:XX:XX:XX (public)
+-- Name: JBL T450BT
+-- Alias: JBL T450BT
+-- Class: 0xFFFFFFFF
+-- Icon: audio-card
+-- Paired: yes
+-- Trusted: yes
+-- Blocked: no
+-- Connected: yes
+-- LegacyPairing: no
+-- UUID: Headset (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
+-- ...
+-- UUID: Handsfree (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
+--
+-- Given this input function returns a following table:
+-- [alias] string JBL T450BT
+-- [blocked] boolean false
+-- [class] string 0x00240404
+-- [connected] boolean true
+-- [icon] string audio
+-- [legacypairing] boolean false
+-- [name] string JBL T450BT
+-- [paired] boolean true
+-- [trusted] boolean true
+function get_device_info(mac_address)
+ if mac_address == nil then
+ mac_address = ""
+ end
+ local device_info = {}
+ local handle = io.popen(string.format("bluetoothctl info %s", mac_address))
+ for line in handle:lines() do
+ local key, value = string.match(line, "(%w+): (.*)")
+ -- Filter junk
+ if key ~= "UUID" and key ~= nil and value ~= nil then
+ key = string.lower(key)
+ if key ~= "name" and key ~= "alias" and key ~= "icon" then
+ if value == "yes" then
+ value = true
+ end
+ if value == "no" then
+ value = false
+ end
+ end
+ device_info[key] = value
+ end
+ end
+ handle:close()
+ return device_info
+end
+
+devices = {}
+
+function reprint_devices(power_state)
+ if power_state then
+ local t = {}
+ for mac_address, device in pairs(devices) do
+ -- table.insert(t, string.format("󰂱 %s", device["alias"]))
+ return "󰂱 "
+ end
+ if next(t) == nil then
+ return "󰂯"
+ else
+ return table.concat(t, separator)
+ end
+ else
+ return "󰂲"
+ end
+end
+
+widget = {
+ plugin = "dbus",
+ opts = {
+ greet = true,
+ -- https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/device-api.txt
+ signals = {
+ {
+ sender = "org.bluez",
+ interface = "org.freedesktop.DBus.Properties",
+ signal = "PropertiesChanged",
+ arg0 = "org.bluez.Device1",
+ bus = "system"
+ }, {
+ sender = "org.bluez",
+ interface = "org.freedesktop.DBus.Properties",
+ signal = "PropertiesChanged",
+ arg0 = "org.bluez.Adapter1",
+ bus = "system"
+ }
+ }
+ },
+ cb = function(t)
+ local power_state = false
+ if t.what == "hello" then
+ power_state = get_power_state()
+ local mac_addresses = get_devices()
+ for i, mac_address in pairs(mac_addresses) do
+ local device = get_device_info(mac_address)
+ if device["connected"] and device["paired"] then
+ devices[mac_address] = device
+ end
+ end
+ elseif t.what == "signal" then
+ -- For reference message from dbus looks like that:
+ -- table
+ -- [1] string org.bluez.Device1
+ -- [2] table
+ -- [2] [1] table
+ -- [2] [1] [1] string SomethingSomething
+ -- [2] [1] [2] boolean false
+ -- [2] [2] table
+ -- [2] [2] [1] string Connected
+ -- [2] [2] [2] boolean true
+ -- [3] table
+ if t.signal == "PropertiesChanged" then
+ power_state = get_power_state()
+ for i, message in pairs(t.parameters[2]) do
+ if message[1] == "Connected" or message[1] == "Paired" then
+ local mac_address = get_device_mac_address(t.object_path)
+ if message[2] then
+ local device = get_device_info(mac_address)
+ if device["paired"] then
+ devices[mac_address] = device
+ end
+ else
+ devices[mac_address] = nil
+ end
+ end
+ end
+ end
+ end
+ return " " .. reprint_devices(power_state)
+ end
+}
diff --git a/.config/luastatus-scripts-dwm/cpu-temperature.lua b/.config/luastatus-scripts-dwm/cpu-temperature.lua
new file mode 100644
index 0000000..38b25d0
--- /dev/null
+++ b/.config/luastatus-scripts-dwm/cpu-temperature.lua
@@ -0,0 +1,45 @@
+paths = {}
+do
+ -- Replace "*" with "[^0]*" in the first glob if your zeroeth thermal sensor is virtual (and
+ -- thus useless):
+ local f = assert(io.popen([[
+ #for file in /sys/class/thermal/thermal_zone*/temp
+ #do
+ # [ -e "$file" ] || break
+ # printf "%s\n" "$file"
+ #done
+for dir in /sys/class/hwmon/*
+do
+ [ -e "$dir" ] || break
+ IFS= read -r monitor_name < "$dir"/name
+ # You may have more than one hardware monitor enabled
+ # If so, disable ones that are not needed
+ case "$monitor_name" in
+ coretemp|fam15h_power|k10temp)
+ printf "%s\n" "$dir"/temp*_input
+ esac
+done
+]]))
+ for p in f:lines() do
+ table.insert(paths, p)
+ end
+ f:close()
+end
+
+widget = {
+ plugin = 'timer',
+ opts = {period = 2},
+ cb = function()
+ for _, p in ipairs(paths) do
+ local f = assert(io.open(p, 'r'))
+ local temp = f:read('*number') / 1000
+ local icon = ""
+ if temp > 55 then
+ icon = ""
+ elseif temp > 80 then
+ icon = ""
+ end
+ return string.format('%s %.0f°C', icon, temp)
+ end
+ end,
+}
diff --git a/.config/luastatus-scripts-dwm/cpu-usage.lua b/.config/luastatus-scripts-dwm/cpu-usage.lua
new file mode 100644
index 0000000..90c75ed
--- /dev/null
+++ b/.config/luastatus-scripts-dwm/cpu-usage.lua
@@ -0,0 +1,7 @@
+widget = luastatus.require_plugin('cpu-usage-linux').widget{
+ cb = function(usage)
+ if usage ~= nil then
+ return string.format('%5.1f%%', usage * 100)
+ end
+ end,
+}
diff --git a/.config/luastatus-scripts-dwm/file-contents.lua b/.config/luastatus-scripts-dwm/file-contents.lua
new file mode 100644
index 0000000..1ed02ac
--- /dev/null
+++ b/.config/luastatus-scripts-dwm/file-contents.lua
@@ -0,0 +1,7 @@
+widget = luastatus.require_plugin('file-contents-linux').widget{
+ filename = "/tmp/bar_status",
+ cb = function(f)
+ -- show the first line of the file
+ return string.format(" %s", f:read('*line'))
+ end,
+}
diff --git a/.config/luastatus-scripts-dwm/fs.lua b/.config/luastatus-scripts-dwm/fs.lua
new file mode 100644
index 0000000..e780dc6
--- /dev/null
+++ b/.config/luastatus-scripts-dwm/fs.lua
@@ -0,0 +1,14 @@
+widget = {
+ plugin = 'fs',
+ opts = {
+ paths = {'/', '/home'},
+ },
+ cb = function(t)
+ local res = {}
+ for k, v in pairs(t) do
+ table.insert(res, string.format('%s %.0f%%', k,
+ (1 - v.avail / v.total) * 100))
+ end
+ return res
+ end,
+}
diff --git a/.config/luastatus-scripts-dwm/ip.lua b/.config/luastatus-scripts-dwm/ip.lua
new file mode 100644
index 0000000..37bc43a
--- /dev/null
+++ b/.config/luastatus-scripts-dwm/ip.lua
@@ -0,0 +1,20 @@
+widget = {
+ plugin = 'network-linux',
+ cb = function(t)
+ local r = {}
+ for iface, params in pairs(t) do
+ local addr = params.ipv4
+ if addr then
+ -- strip out "label" from the interface name
+ iface = iface:gsub(':.*', '')
+ -- strip out "zone index" from the address
+ addr = addr:gsub('%%.*', '')
+
+ if iface ~= 'lo' then
+ r[#r + 1] = string.format('[%s: %s]', iface, addr)
+ end
+ end
+ end
+ return r
+ end,
+}
diff --git a/.config/luastatus-scripts-dwm/mem-usage.lua b/.config/luastatus-scripts-dwm/mem-usage.lua
new file mode 100644
index 0000000..1c34219
--- /dev/null
+++ b/.config/luastatus-scripts-dwm/mem-usage.lua
@@ -0,0 +1,7 @@
+widget = luastatus.require_plugin('mem-usage-linux').widget{
+ timer_opts = {period = 2},
+ cb = function(t)
+ local used_kb = t.total.value - t.avail.value
+ return string.format('  %3.2f GiB ', used_kb / 1024 / 1024)
+ end,
+}
diff --git a/.config/luastatus-scripts-dwm/mpd.lua b/.config/luastatus-scripts-dwm/mpd.lua
new file mode 100644
index 0000000..32cddc6
--- /dev/null
+++ b/.config/luastatus-scripts-dwm/mpd.lua
@@ -0,0 +1,32 @@
+-- you need to install 'utf8' module (e.g. with luarocks) if using Lua <=5.2.
+utf8 = require 'utf8'
+
+titlewidth = 40
+
+widget = {
+ plugin = 'mpd',
+ cb = function(t)
+ if t.what == 'update' then
+ local title
+ if t.song.Title then
+ title = t.song.Title
+ if t.song.Artist then
+ title = t.song.Artist .. ': ' .. title
+ end
+ else
+ title = t.song.file or ''
+ end
+ title = (utf8.len(title) <= titlewidth)
+ and title
+ or utf8.sub(title, 1, titlewidth - 1) .. '…'
+
+ return string.format('%s %s',
+ ({play = '▶', pause = '‖', stop = '■'})[t.status.state],
+ title
+ )
+ else
+ -- 'connecting' or 'error'
+ return t.what
+ end
+ end
+}
diff --git a/.config/luastatus-scripts-dwm/network.lua b/.config/luastatus-scripts-dwm/network.lua
new file mode 100644
index 0000000..4ec808a
--- /dev/null
+++ b/.config/luastatus-scripts-dwm/network.lua
@@ -0,0 +1,72 @@
+local MIN_DBM, MAX_DBM = -90, -20
+local NGAUGE = 5
+local COLOR_DIM = '#709080'
+
+local function round(x)
+ return math.floor(x + 0.5)
+end
+
+local function make_wifi_gauge(dbm)
+ if dbm < MIN_DBM then dbm = MIN_DBM end
+ if dbm > MAX_DBM then dbm = MAX_DBM end
+ local nbright = round(NGAUGE * (1 - 0.7 * (MAX_DBM - dbm) / (MAX_DBM - MIN_DBM)))
+
+ if nbright == 0 then
+ return "󰤭"
+ elseif nbright == 1 then
+ return "󰤯"
+ elseif nbright == 2 then
+ return "󰤟"
+ elseif nbright == 3 then
+ return "󰤢"
+ elseif nbright == 4 then
+ return "󰤥"
+ else
+ return "󰤨"
+ end
+end
+
+widget = {
+ plugin = 'network-linux',
+ opts = {
+ wireless = true,
+ timeout = 10,
+ },
+ cb = function(t)
+ if not t then
+ return nil
+ end
+
+ local x = ""
+ local sep = " "
+
+ if t.eno1 then
+ if t.eno1.ipv4 or t.eno1.ipv6 then
+ x = ""
+ end
+ end
+
+ if t.enp5s0f3u1 then
+ if x ~= "" then
+ x = x .. sep
+ end
+ if t.enp5s0f3u1.ipv4 or t.enp5s0f3u1.ipv6 then
+ x = x .. "󱎔"
+ end
+ end
+
+ if t.wlo1.wireless then
+ if x ~= "" then
+ x = x .. sep
+ end
+ if t.wlo1.wireless.signal_dbm then
+ x = x .. make_wifi_gauge(t.wlo1.wireless.signal_dbm)
+ else
+ x = x .. "󰤭"
+ end
+ end
+
+ x = " " .. x .. " "
+ return x
+ end,
+}
diff --git a/.config/luastatus-scripts-dwm/pulse-gauge.lua b/.config/luastatus-scripts-dwm/pulse-gauge.lua
new file mode 100644
index 0000000..dbc5c67
--- /dev/null
+++ b/.config/luastatus-scripts-dwm/pulse-gauge.lua
@@ -0,0 +1,18 @@
+local GAUGE_NCHARS = 10
+
+local function mk_gauge(level, full, empty)
+ local nfull = math.floor(level * GAUGE_NCHARS + 0.5)
+ return full:rep(nfull) .. empty:rep(GAUGE_NCHARS - nfull)
+end
+
+widget = {
+ plugin = 'pulse',
+ cb = function(t)
+ local level = t.cur / t.norm
+ if t.mute then
+ return mk_gauge(level, '×', '—')
+ else
+ return mk_gauge(level, '●', '○')
+ end
+ end,
+}
diff --git a/.config/luastatus-scripts-dwm/pulse.lua b/.config/luastatus-scripts-dwm/pulse.lua
new file mode 100644
index 0000000..59b73e8
--- /dev/null
+++ b/.config/luastatus-scripts-dwm/pulse.lua
@@ -0,0 +1,10 @@
+widget = {
+ plugin = 'pulse',
+ cb = function(t)
+ if t.mute then
+ return '[mute]'
+ end
+ local percent = (t.cur / t.norm) * 100
+ return string.format('[%3d%%]', math.floor(0.5 + percent))
+ end,
+}
diff --git a/.config/luastatus-scripts-dwm/time-date.lua b/.config/luastatus-scripts-dwm/time-date.lua
new file mode 100644
index 0000000..8fce7a1
--- /dev/null
+++ b/.config/luastatus-scripts-dwm/time-date.lua
@@ -0,0 +1,58 @@
+months = {'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'}
+wday = {'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'}
+widget = {
+ plugin = 'timer',
+ cb = function()
+ local d = os.date('*t')
+
+ if d.hour < 12 then
+ suffix = "a.m."
+ else
+ suffix = "p.m."
+ d.hour = d.hour - 12
+ end
+
+ local date_suffix = "th"
+ if not (d.day % 100 >= 11 and d.day % 100 <= 13) then
+ local last_digit = d.day % 10
+ if last_digit == 1 then
+ date_suffix = "st"
+ elseif last_digit == 2 then
+ date_suffix = "nd"
+ elseif last_digit == 3 then
+ date_suffix = "rd"
+ end
+ end
+
+ local time_icon = ""
+ if d.hour == 0 or d.hour == 12 then
+ time_icon = "󱑖"
+ elseif d.hour == 1 then
+ time_icon = "󱑋"
+ elseif d.hour == 2 then
+ time_icon = "󱑌"
+ elseif d.hour == 3 then
+ time_icon = "󱑍"
+ elseif d.hour == 4 then
+ time_icon = "󱑎"
+ elseif d.hour == 5 then
+ time_icon = "󱑏"
+ elseif d.hour == 6 then
+ time_icon = "󱑐"
+ elseif d.hour == 7 then
+ time_icon = "󱑑"
+ elseif d.hour == 8 then
+ time_icon = "󱑒"
+ elseif d.hour == 9 then
+ time_icon = "󱑓"
+ elseif d.hour == 10 then
+ time_icon = "󱑔"
+ elseif d.hour == 11 then
+ time_icon = "󱑕"
+ end
+
+ return {
+ string.format('󰃭 %d%s %s %d (%s) %s %d:%02d %s ', d.day, date_suffix, months[d.month], d.year, wday[d.wday], time_icon, d.hour, d.min, suffix),
+ }
+ end,
+}
diff --git a/.config/luastatus-scripts-dwm/tor.lua b/.config/luastatus-scripts-dwm/tor.lua
new file mode 100644
index 0000000..db97225
--- /dev/null
+++ b/.config/luastatus-scripts-dwm/tor.lua
@@ -0,0 +1,13 @@
+-- Trivial but somewhat useful widget showing if the Tor daemon is running.
+
+widget = {
+ plugin = 'timer',
+ opts = {period = 5},
+ cb = function()
+ local f = io.open('/var/run/tor/tor.pid', 'r')
+ if f then
+ f:close()
+ return '[TOR]'
+ end
+ end,
+}
diff --git a/.config/luastatus-scripts-dwm/weather.lua b/.config/luastatus-scripts-dwm/weather.lua
new file mode 100644
index 0000000..d626689
--- /dev/null
+++ b/.config/luastatus-scripts-dwm/weather.lua
@@ -0,0 +1,67 @@
+-- you need to install 'luasec' module (e.g. with luarocks)
+-- you can look up all available flags here: https://github.com/chubin/wttr.in#one-line-output
+
+local https = require('ssl.https')
+local ltn12 = require('ltn12')
+
+-- All the arguments except for 'url' may be absent or nil; default method is GET.
+-- Returns: code (integer), body (string), headers (table), status (string).
+function request(url, headers, method, body)
+ local out_body = {}
+ local is_ok, code_or_errmsg, out_headers, status = https.request(
+ {
+ url = url,
+ sink = ltn12.sink.table(out_body),
+ redirect = false,
+ cafile = '/etc/ssl/certs/ca-certificates.crt',
+ verify = 'peer',
+ method = method,
+ headers = headers,
+ },
+ body)
+ assert(is_ok, code_or_errmsg)
+ return code_or_errmsg, table.concat(out_body), out_headers, status
+end
+
+-- Arguments are the same to those of 'request'.
+-- Returns: body (string), headers (table).
+function request_check_code(...)
+ local code, body, headers, status = request(...)
+ assert(code == 200, string.format('HTTP %s %s', code, status))
+ return body, headers
+end
+
+function urlencode(s)
+ return string.gsub(s, '[^-_.~a-zA-Z0-9]', function(c)
+ return string.format('%%%02X', string.byte(c))
+ end)
+end
+
+local BASE_URL = 'wttr.in'
+local LANG = 'en'
+local LOCATION = ''
+
+function get_weather(format)
+ -- encoding is needed to allow usage of special use characters
+ format = urlencode(format)
+ local url = string.format('https://%s.%s/%s?format=%s', LANG, BASE_URL, LOCATION, format)
+ local is_ok, body = pcall(request_check_code, url)
+ if is_ok then
+ return body:gsub("\n", "")
+ else
+ return nil
+ end
+end
+
+widget = {
+ plugin = 'timer',
+ opts = {period = 15 * 60},
+ cb = function()
+ local text = get_weather('%l: %C %t(%f)')
+ if text == nil then
+ luastatus.plugin.push_period(60) -- retry in 60 seconds
+ text = '......'
+ end
+ return text
+ end,
+}
diff --git a/.config/luastatus-scripts-dwm/xkb.lua b/.config/luastatus-scripts-dwm/xkb.lua
new file mode 100644
index 0000000..358f0d7
--- /dev/null
+++ b/.config/luastatus-scripts-dwm/xkb.lua
@@ -0,0 +1,17 @@
+widget = {
+ plugin = 'xkb',
+ cb = function(t)
+ if t.name then
+ local base_layout = t.name:match('[^(]+')
+ if base_layout == 'gb' or base_layout == 'us' then
+ return '[En]'
+ elseif base_layout == 'ru' then
+ return '[Ru]'
+ else
+ return '[' .. base_layout:sub(1, 1):upper() .. base_layout:sub(2) .. ']'
+ end
+ else
+ return '[? ID ' .. t.id .. ']'
+ end
+ end,
+}