Merge pull request #492 from hcpl/xkblayout

Xkblayout: refine formatting and switching layouts
This commit is contained in:
enkore 2017-01-11 12:39:52 +01:00 committed by GitHub
commit dd2d9407e3
2 changed files with 69 additions and 33 deletions

View File

@ -47,6 +47,7 @@ MOCK_MODULES = [
"dateutil.parser", "dateutil.parser",
"dateutil.relativedelta", "dateutil.relativedelta",
"redshift_gtk.statusicon", "redshift_gtk.statusicon",
"xkbgroup",
] ]
for mod_name in MOCK_MODULES: for mod_name in MOCK_MODULES:

View File

@ -1,5 +1,8 @@
from i3pystatus import IntervalModule
import subprocess import subprocess
from itertools import zip_longest
from i3pystatus import IntervalModule
from xkbgroup import XKeyboard
class Xkblayout(IntervalModule): class Xkblayout(IntervalModule):
@ -11,49 +14,81 @@ class Xkblayout(IntervalModule):
is enabled. is enabled.
``layouts`` can be stated with or without variants, ``layouts`` can be stated with or without variants,
e.g.: status.register("xkblayout", layouts=["de neo", "de"]) 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 interval = 1
format = u"\u2328 {name}" format = "\u2328 {symbol}"
layouts = []
uppercase = True uppercase = True
settings = ( settings = (
("format", "Format string"), ("format", "Format string"),
("layouts", "List of layouts"), ("layouts", "List of layouts"),
("uppercase", "Flag for uppercase output"), ("uppercase", "Flag for uppercase output"),
) )
layouts = []
on_leftclick = "change_layout" 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): def run(self):
kblayout = self.kblayout() cdict = {
"num": self._xkb.group_num,
full_text = self.format.format(name=kblayout) "name": self._xkb.group_name,
if self.uppercase: "symbol": self._xkb.group_symbol,
full_text = full_text.upper() "variant": self._xkb.group_variant,
"count": self._xkb.groups_count,
self.output = { "names": self._xkb.groups_names,
"full_text": full_text, "symbols": self._xkb.groups_symbols,
"color": "#ffffff" "variants": self._xkb.groups_variants,
} }
def change_layout(self): full_text = self.format.format(**cdict)
layouts = self.layouts full_text = full_text.upper() if self.uppercase else full_text
kblayout = self.kblayout()
if kblayout in layouts:
position = layouts.index(kblayout)
try:
subprocess.check_call(["setxkbmap"] +
layouts[position + 1].split())
except IndexError:
subprocess.check_call(["setxkbmap"] + layouts[0].split())
else:
subprocess.check_call(["setxkbmap"] + layouts[0].split())
def kblayout(self): self.data = cdict
kblayout = subprocess.check_output("setxkbmap -query", shell=True)\ self.output = {
.decode("utf-8").splitlines() "full_text": full_text,
kblayout = [l.split() for l in kblayout] "color": "#FFFFFF",
kblayout = [l[1].strip() for l in kblayout }
if l[0].startswith(("layout", "variant"))]
return (" ").join(kblayout)