Test multiplatform support
Testing changes to better support other platforms
This commit is contained in:
+233
@@ -0,0 +1,233 @@
|
||||
--- Battery module for Wezterm.
|
||||
---@module "battery"
|
||||
|
||||
---@class M The battery module
|
||||
---@field invert boolean Whether to invert colors
|
||||
---@function get_batteries() Get the list of batteries
|
||||
---@function get_battery_icons() Get the battery icons
|
||||
---@function get_battery_stats() Get the battery stats
|
||||
|
||||
local M = {}
|
||||
|
||||
local wezterm = require("wezterm")
|
||||
|
||||
--- Whether to invert the colors for light backgrounds.
|
||||
M.invert = false
|
||||
|
||||
--- Converts a hex color to its opposite brightness.
|
||||
---@param hex_color string The hex color in the format "#RRGGBB".
|
||||
---@param invert? boolean Whether to invert the colors (optional).
|
||||
---@return string hex_color The hex color with the opposite brightness.
|
||||
local function invert_color_brightness(hex_color, invert)
|
||||
if invert == nil then
|
||||
invert = M.invert
|
||||
end
|
||||
if invert == false then
|
||||
return hex_color
|
||||
end
|
||||
-- Validate the input hex_color format.
|
||||
if not hex_color:match("^#%x%x%x%x%x%x$") then
|
||||
error("Invalid hex color format. Use #RRGGBB.")
|
||||
end
|
||||
|
||||
-- Convert hex to RGB.
|
||||
local r = tonumber(hex_color:sub(2, 3), 16)
|
||||
local g = tonumber(hex_color:sub(4, 5), 16)
|
||||
local b = tonumber(hex_color:sub(6, 7), 16)
|
||||
|
||||
-- Validate RGB values.
|
||||
if not (r and g and b and r >= 0 and r <= 255 and g >= 0 and g <= 255 and b >= 0 and b <= 255) then
|
||||
error("Invalid RGB values extracted from hex color.")
|
||||
end
|
||||
|
||||
-- Calculate brightness.
|
||||
local brightness = (r * 0.299 + g * 0.587 + b * 0.114)
|
||||
|
||||
-- Invert color based on brightness.
|
||||
if brightness < 128 then
|
||||
-- Dark color: make it lighter.
|
||||
r = math.min(r + (255 - r) * 0.33, 255)
|
||||
g = math.min(g + (255 - g) * 0.33, 255)
|
||||
b = math.min(b + (255 - b) * 0.33, 255)
|
||||
else
|
||||
-- Light color: make it darker.
|
||||
r = math.max(r - r * 0.66, 0)
|
||||
g = math.max(g - g * 0.66, 0)
|
||||
b = math.max(b - b * 0.66, 0)
|
||||
end
|
||||
|
||||
-- Convert RGB back to hex.
|
||||
return string.format("#%02x%02x%02x", math.floor(r + 0.5), math.floor(g + 0.5), math.floor(b + 0.5))
|
||||
end
|
||||
|
||||
--- RGBColor class representing an RGB color.
|
||||
---@class RGBColor
|
||||
---@field r number Red value (0-255).
|
||||
---@field g number Green value (0-255).
|
||||
---@field b number Blue value (0-255).
|
||||
|
||||
--- Blends two RGB colors together based on a blend factor.
|
||||
---@param color1 RGBColor The first RGB color.
|
||||
---@param color2 RGBColor The second RGB color.
|
||||
---@param factor number The blend factor (between 0 and 1).
|
||||
---@return RGBColor color The blended RGB color.
|
||||
local function blend_color(color1, color2, factor)
|
||||
return {
|
||||
r = color1.r + (color2.r - color1.r) * factor,
|
||||
g = color1.g + (color2.g - color1.g) * factor,
|
||||
b = color1.b + (color2.b - color1.b) * factor,
|
||||
}
|
||||
end
|
||||
|
||||
--- Rounds a decimal value to the nearest integer.
|
||||
---@param val number The value to round.
|
||||
---@return integer The rounded value.
|
||||
local function round(val)
|
||||
return math.floor(val + 0.5)
|
||||
end
|
||||
|
||||
--- Converts an RGB color to a hex string.
|
||||
---@param color RGBColor The RGB color to convert.
|
||||
---@return string hex_color The hex string representation of the color.
|
||||
local function rgb_to_hex(color)
|
||||
return string.format("#%02x%02x%02x", round(color.r), round(color.g), round(color.b))
|
||||
end
|
||||
|
||||
--- Gets the color representing a battery charge level.
|
||||
---@param charge number The charge level (0.0 to 1.0).
|
||||
---@return string hex_color The corresponding hex color.
|
||||
local function get_charge_color(charge)
|
||||
local red = { r = 255, g = 0, b = 0 }
|
||||
local yellow = { r = 255, g = 255, b = 0 }
|
||||
local green = { r = 0, g = 255, b = 0 }
|
||||
local color = {}
|
||||
|
||||
if charge <= 0.5 then
|
||||
local factor = charge / 0.5
|
||||
color = blend_color(red, yellow, factor)
|
||||
else
|
||||
local factor = (charge - 0.5) / 0.5
|
||||
color = blend_color(yellow, green, factor)
|
||||
end
|
||||
|
||||
return invert_color_brightness(rgb_to_hex(color))
|
||||
end
|
||||
|
||||
--- BatteryComponent class representing battery information.
|
||||
---@class BatteryComponent
|
||||
---@field battery string The battery icon and percentage. (e.g. " 100%")
|
||||
---@field remaining fun(): string The remaining time as a string. (e.g. "10:00")
|
||||
---@field icon string The icon representing the battery status. (e.g. " ")
|
||||
---@field percent number The battery percentage. (0.0 to 1.0)
|
||||
---@field time number The remaining time in minutes.
|
||||
---@field condition string The battery condition ("Full", "Empty", "Charging", "Discharging", "Unknown").
|
||||
|
||||
--- Returns battery components for each battery.
|
||||
--- If no batteries are detected, an empty table is returned.
|
||||
---@return BatteryComponent[] batteries A list of battery components.
|
||||
---@see BatteryComponent
|
||||
function M.get_batteries()
|
||||
local batteries = {}
|
||||
local battery_info = wezterm.battery_info()
|
||||
|
||||
local icons_charging =
|
||||
{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " " }
|
||||
local icons_discharging =
|
||||
{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " " }
|
||||
|
||||
for _, b in ipairs(battery_info) do
|
||||
local condition = b.state
|
||||
local charge = b.state_of_charge
|
||||
local remaining = 0
|
||||
local percent = charge * 100
|
||||
local icon = -- Default battery state is Unknown
|
||||
wezterm.format({ { Foreground = { Color = invert_color_brightness("#232634") } }, { Text = " " } })
|
||||
|
||||
if condition == "Full" then -- Battery is 100% charged
|
||||
icon =
|
||||
wezterm.format({ { Foreground = { Color = invert_color_brightness("#93e398") } }, { Text = " " } })
|
||||
elseif condition == "Empty" then -- Battery is 0% charged
|
||||
icon =
|
||||
wezterm.format({ { Foreground = { Color = invert_color_brightness("#f37ca0") } }, { Text = " " } })
|
||||
elseif condition == "Charging" then -- Battery is charging
|
||||
remaining = b.time_to_full
|
||||
icon = wezterm.format({
|
||||
{ Foreground = { Color = get_charge_color(charge) } },
|
||||
{ Text = icons_charging[math.min(math.ceil(charge * 10), 11)] },
|
||||
})
|
||||
elseif condition == "Discharging" then -- Battery is discharging
|
||||
remaining = b.time_to_empty
|
||||
icon = wezterm.format({
|
||||
{ Foreground = { Color = get_charge_color(charge) } },
|
||||
{ Text = icons_discharging[math.min(math.ceil(charge * 10), 11)] },
|
||||
})
|
||||
elseif condition == "Unknown" and charge > 0.5 then -- Battery is (probably) at charge limit
|
||||
icon =
|
||||
wezterm.format({ { Foreground = { Color = invert_color_brightness("#93e398") } }, { Text = " " } })
|
||||
end
|
||||
|
||||
table.insert(batteries, {
|
||||
battery = icon .. string.format("%.2f%%", percent),
|
||||
remaining = function()
|
||||
if remaining and remaining > 0 then
|
||||
return string.format("%d:%02d", math.floor(remaining / 60), math.floor(remaining % 60))
|
||||
else
|
||||
return ""
|
||||
end
|
||||
end,
|
||||
icon = icon,
|
||||
percent = percent,
|
||||
time = remaining,
|
||||
condition = condition,
|
||||
})
|
||||
end
|
||||
|
||||
return batteries
|
||||
end
|
||||
|
||||
--- Returns battery icons for all batteries.
|
||||
--- If no batteries are detected, an empty string is returned.
|
||||
---@return string battery_icons A formatted string containing the battery icons.
|
||||
function M.get_battery_icons()
|
||||
local battery_states = M.get_batteries()
|
||||
|
||||
if #battery_states == 0 then
|
||||
return ""
|
||||
end
|
||||
|
||||
local result = {}
|
||||
for _, state in ipairs(battery_states) do
|
||||
table.insert(result, state.icon)
|
||||
end
|
||||
|
||||
return table.concat(result, " | ")
|
||||
end
|
||||
|
||||
--- Returns battery statistics for all batteries.
|
||||
--- If no batteries are detected, an empty string is returned.
|
||||
---@return string battery_stats A formatted string containing the battery stats.
|
||||
function M.get_battery_stats()
|
||||
local battery_states = M.get_batteries()
|
||||
|
||||
if #battery_states == 0 then
|
||||
return ""
|
||||
end
|
||||
|
||||
local result = {}
|
||||
for _, state in ipairs(battery_states) do
|
||||
local color = get_charge_color(state.percent / 100)
|
||||
local percent = wezterm.format({
|
||||
{ Foreground = { Color = color } },
|
||||
{ Text = string.format(" (%.2f%%)", state.percent) },
|
||||
})
|
||||
local remaining_time = wezterm.format({
|
||||
{ Foreground = { Color = color } },
|
||||
{ Text = state.remaining() },
|
||||
})
|
||||
table.insert(result, string.format("%s%s", state.icon, percent) .. remaining_time)
|
||||
end
|
||||
|
||||
return table.concat(result, " | ")
|
||||
end
|
||||
|
||||
return M
|
||||
Reference in New Issue
Block a user