diff --git a/i3pystatus/battery.py b/i3pystatus/battery.py index e812e76..74374c5 100644 --- a/i3pystatus/battery.py +++ b/i3pystatus/battery.py @@ -5,7 +5,7 @@ import re from i3pystatus import IntervalModule, formatp from i3pystatus.core.command import run_through_shell from i3pystatus.core.desktop import DesktopNotification -from i3pystatus.core.util import lchop, TimeWrapper, make_bar +from i3pystatus.core.util import lchop, TimeWrapper, make_bar, make_glyph class UEventParser(configparser.ConfigParser): @@ -141,6 +141,7 @@ class BatteryChecker(IntervalModule): * `{battery_ident}` — the same as the setting * `{bar}` —bar displaying the relative percentage graphically * `{bar_design}` —bar displaying the absolute percentage graphically + * `{glyph}` — A single character or string (selected from 'glyphs') representing the current battery percentage This module supports the :ref:`formatp ` extended string format syntax. By setting the ``FULL`` status to an empty string, and including @@ -195,6 +196,7 @@ class BatteryChecker(IntervalModule): ("not_present_text", "The text to display when the battery is not present. Provides {battery_ident} as formatting option"), ("no_text_full", "Don't display text when battery is full - 100%"), + ("glyphs", "Arbitrarily long string of characters (or array of strings) to represent battery charge percentage"), ) battery_ident = "ALL" @@ -220,6 +222,7 @@ class BatteryChecker(IntervalModule): critical_color = "#ff0000" not_present_color = "#ffffff" no_text_full = False + glyphs = "▁▂▃▄▅▆▇█" battery_prefix = 'BAT' base_path = '/sys/class/power_supply' @@ -318,6 +321,7 @@ class BatteryChecker(IntervalModule): "percentage_design": self.percentage(batteries, design=True), "consumption": self.consumption(batteries), "remaining": TimeWrapper(0, "%E%h:%M"), + "glyph": make_glyph(self.percentage(batteries), self.glyphs), "bar": make_bar(self.percentage(batteries)), "bar_design": make_bar(self.percentage(batteries, design=True)), } diff --git a/i3pystatus/core/util.py b/i3pystatus/core/util.py index 8e7c698..5d9bd71 100644 --- a/i3pystatus/core/util.py +++ b/i3pystatus/core/util.py @@ -523,6 +523,53 @@ def make_bar(percentage): return result +def make_glyph(number, glyphs="▁▂▃▄▅▆▇█", lower_bound=0, upper_bound=100, enable_boundary_glyphs=False): + """ + Returns a single glyph from the list of glyphs provided relative to where + the number is in the range (by default a percentage value is expected). + + This can be used to create an icon based representation of a value with an + arbitrary number of glyphs (e.g. 4 different battery status glyphs for + battery percentage level). + + :param number: The number being represented. By default a percentage value\ + between 0 and 100 (but any range can be defined with lower_bound and\ + upper_bound). + :param glyphs: Either a string of glyphs, or an array of strings. Using an array\ + of strings allows for additional pango formatting to be applied such that\ + different colors could be shown for each glyph). + :param lower_bound: A custom lower bound value for the range. + :param upper_bound: A custom upper bound value for the range. + :param enable_boundary_glyphs: Whether the first and last glyphs should be used\ + for the special case of the number being <= lower_bound or >= upper_bound\ + respectively. + :returns: The glyph found to represent the number + """ + + # Handle edge cases first + if lower_bound >= upper_bound: + raise Exception("Invalid upper/lower bounds") + elif number <= lower_bound: + return glyphs[0] + elif number >= upper_bound: + return glyphs[-1] + + if enable_boundary_glyphs: + # Trim first and last items from glyphs as boundary conditions already + # handled + glyphs = glyphs[1:-1] + + # Determine a value 0 - 1 that represents the position in the range + adjusted_value = (number - lower_bound) / (upper_bound - lower_bound) + + # Determine the closest glyph to show + # As we have positive indices, we can use int for floor rounding + # Adjusted_value should always be < 1 + glyph_index = int(len(glyphs) * adjusted_value) + + return glyphs[glyph_index] + + def user_open(url_or_command): """Open the specified paramater in the web browser if a URL is detected, othewrise pass the paramater to the shell as a subprocess. This function