str(Path(__file__).resolve().parents[2] / '.local' / 'bin' / 'lib'))
from pactl import pactl_info_default_dev
-METADATA = {'version': 1}
-
COL_GREEN = '#00DD00'
COL_GREY = '#AAAAAA'
COL_RED = '#DD0000'
COL_YELLOW = '#DDDD00'
COL_ESCALATION = (COL_GREEN, COL_YELLOW, COL_RED)
-CMD_PASTE = 'wl-paste'
-CLIP_LEN_MAX = 32
-MSG_CLIPBOARD_EMPTY = 'Nothing is copied'
-
-KB_LAYOUTS = ('us', 'de') # keep in sync with sway config's xkb_layout
-
-AUDIO_DEVS_LABELS = (('sink', 'vol'),
- ('source', '--mic'))
-
-PATH_POWER_SUPPLY = Path('/sys/class/power_supply')
-GLOB_BATTERY = 'BAT*'
+# for blocks_battery
BATTERY_STATUS_SYMBOLS = {
'Charging': ('^', COL_GREEN),
'Discharging': ('v', COL_RED),
'Not charging': ('-', COL_WHITE),
}
+BATTERY_ESCALATIONS_CHARGE = (85, 25)
+BATTERY_ESCALATIONS_HEALTH = (85, 25)
+
+# for blocks_clipboard
+CMD_PASTE = 'wl-paste'
+CLIP_LEN_MAX = 32
-PATH_THERMAL = Path('/sys/class/thermal')
-GLOB_THERMAL = 'thermal_zone*/temp'
+# for blocks_layout
+KB_LAYOUTS = ('us', 'de') # keep in sync with sway config's xkb_layout
+
+# for blocks_network
+NETWORK_STRENGTH_ESCALATIONS = (80, 50)
+
+# for blocks_thermal
+THERMAL_ESCALATIONS = (55, 80)
class Block(NamedTuple):
return items.pop()
-def blocks_clipboard(
- ) -> tuple[Block, ...]:
- 'Produce clipboard contents summary.'
- blocks = []
- args: tuple[str, ...]
- for args in (tuple(), ('--primary',)):
- col_clip = COL_YELLOW
- brackets = '()'
- proc = subprocess_run((CMD_PASTE,) + args,
- check=False, capture_output=True)
- if proc.returncode:
- stderr = proc.stderr.decode('utf8', 'replace').strip()
- if stderr == MSG_CLIPBOARD_EMPTY:
- clip = 'empty'
- col_clip = COL_GREY
- else:
- clip = 'error'
- col_clip = COL_RED
- else:
- try:
- clip = proc.stdout.decode('utf8').replace('\n', ' ').strip()
- brackets = '[]'
- except UnicodeDecodeError:
- clip = 'binary'
- if (ellipsed := len(clip) > CLIP_LEN_MAX):
- clip = clip[:CLIP_LEN_MAX - 1]
- blocks += [Block(f'{(args[0] if args else CMD_PASTE)} {brackets[0]}'),
- Block(clip, col_clip)]
- if ellipsed:
- blocks += [Block('…', COL_GREEN)]
- blocks += [Block(brackets[1], separator_block_width=5)]
- return tuple(blocks)
-
-
def blocks_audio(
) -> tuple[Block, ...]:
"Produce audio devices' volume, muteness."
blocks = []
- for dev_type, label in AUDIO_DEVS_LABELS:
+ for dev_type, label in (('sink', 'vol'),
+ ('source', '--mic')):
dev_info = pactl_info_default_dev(dev_type)
is_mute = dev_info['mute']
percentage = first_among_equals(
def blocks_battery(
) -> tuple[Block, ...]:
'Produce battery charge, status, health status bar text.'
- path_battery = next(PATH_POWER_SUPPLY.glob(GLOB_BATTERY))
+ path_battery = next(Path('/sys/class/power_supply').glob('BAT*'))
status, status_color = BATTERY_STATUS_SYMBOLS.get(
(path_battery / 'status').read_text(encoding='utf8').strip(),
('?', COL_RED))
charge_pc = round(now / full * 100)
health_pc = round(full / full_design * 100)
break
- return (Block.color_escalated(charge_pc, (85, 25)),
+ return (Block.color_escalated(charge_pc, BATTERY_ESCALATIONS_CHARGE),
Block(status, status_color),
- Block.color_escalated(health_pc, (85, 25)))
+ Block.color_escalated(health_pc, BATTERY_ESCALATIONS_HEALTH))
+
+
+def blocks_clipboard(
+ ) -> tuple[Block, ...]:
+ 'Produce clipboard contents summary.'
+ blocks = []
+ args: tuple[str, ...]
+ for args in (tuple(), ('--primary',)):
+ col_clip = COL_YELLOW
+ brackets = '()'
+ proc = subprocess_run((CMD_PASTE,) + args,
+ check=False, capture_output=True)
+ if proc.returncode:
+ stderr = proc.stderr.decode('utf8', 'replace').strip()
+ if stderr == 'Nothing is copied':
+ clip = 'empty'
+ col_clip = COL_GREY
+ else:
+ clip = 'error'
+ col_clip = COL_RED
+ else:
+ try:
+ clip = proc.stdout.decode('utf8').replace('\n', ' ').strip()
+ brackets = '[]'
+ except UnicodeDecodeError:
+ clip = 'binary'
+ if (ellipsed := len(clip) > CLIP_LEN_MAX):
+ clip = clip[:CLIP_LEN_MAX - 1]
+ blocks += [Block(f'{(args[0] if args else CMD_PASTE)} {brackets[0]}'),
+ Block(clip, col_clip)]
+ if ellipsed:
+ blocks += [Block('…', COL_GREEN)]
+ blocks += [Block(brackets[1], separator_block_width=5)]
+ return tuple(blocks)
def blocks_datetime(
blocks += [Block(f'{dev_type} ')]
if len(info_toks) == 3:
percentage = int(info_toks[2])
- blocks += [Block.color_escalated(percentage, (80, 50)),
+ blocks += [Block.color_escalated(percentage,
+ NETWORK_STRENGTH_ESCALATIONS),
Block('% ')]
blocks += [Block('/'.join(info_toks[:2]), COL_WHITE,
separator_block_width=5)]
) -> tuple[Block, ...]:
'Produce Celsius of current device hotness.'
temperature = round(max(int_at_path(path)
- for path in PATH_THERMAL.glob(GLOB_THERMAL)) / 1000)
- return (Block.color_escalated(temperature, (55, 80)),
+ for path in Path('/sys/class/thermal'
+ ).glob('thermal_zone*/temp')) / 1000)
+ return (Block.color_escalated(temperature, THERMAL_ESCALATIONS),
Block('°C'))
def print_bar(
) -> None:
'Produce stream of status bar updates.'
- print(json_dumps(METADATA))
+ print(json_dumps({'version': 1}))
print('[', end='')
while True:
blocks: list[Block] = []