Source code for i3pystatus.xkblayout

import subprocess
from itertools import zip_longest

from i3pystatus import IntervalModule
from xkbgroup import XKeyboard

[docs]class Xkblayout(IntervalModule): """Displays and changes current keyboard layout. ``change_layout`` callback finds the current layout in the ``layouts`` setting and enables the layout following it. If the current layout is not in the ``layouts`` setting the first layout is enabled. ``layouts`` can be stated with or without variants, e.g.: ``status.register("xkblayout", layouts=["de neo", "de"])`` Requires xkbgroup (from PyPI) .. rubric:: Available formatters * `{num}` — current group number * `{name}` — current group name * `{symbol}` — current group symbol * `{variant}` — current group variant * `{count}` — number of all groups * `{names}` — names of all groups * `{symbols}` — symbols of all groups * `{variants}` — variants of all groups """ interval = 1 color = "#FFFFFF" format = "\u2328 {symbol}" layouts = [] uppercase = True settings = ( ("color", "RGB hexadecimal color code specifuer, defaults to #FFFFFF"), ("format", "Format string"), ("layouts", "List of layouts"), ("uppercase", "Flag for uppercase output"), ) on_leftclick = ["change_layout", 1] on_upscroll = ["change_layout", 1] on_downscroll = ["change_layout", -1] def init(self): if self.layouts: self.set_layouts(self.layouts) self._xkb = XKeyboard(auto_open=True) def set_layouts(self, layouts): self.layouts = layouts # Set, so that it could be used as a callback layouts_parts = [x.split() for x in self.layouts] symbols_variants_zipped = zip_longest(*layouts_parts, fillvalue="") symbols_variants_str = [",".join(x) for x in symbols_variants_zipped] assert len(symbols_variants_str) > 0 if len(symbols_variants_str) == 1: symbols = symbols_variants_str[0] args = "setxkbmap -layout {}".format(symbols) elif len(symbols_variants_str) == 2: (symbols, variants) = symbols_variants_str args = "setxkbmap -layout {} -variant {}".format(symbols, variants) else: raise ValueError("Wrong layouts value: {}".format(self.layouts)) subprocess.check_call(args.split()) def change_layout(self, increment=1): self._xkb.group_num += increment def run(self): cdict = { "num": self._xkb.group_num, "name": self._xkb.group_name, "symbol": self._xkb.group_symbol, "variant": self._xkb.group_variant, "count": self._xkb.groups_count, "names": self._xkb.groups_names, "symbols": self._xkb.groups_symbols, "variants": self._xkb.groups_variants, } full_text = self.format.format(**cdict) full_text = full_text.upper() if self.uppercase else full_text = cdict self.output = { "full_text": full_text, "color": self.color, }