Xkblayout: refine formatting and switching layouts
Introduces PyPI package xkbgroup as a dependency. Changes include: * Add more formatters - Backwards-incompatible: ``{name}`` now refers to the layout group name, such as 'English (US)' or 'German'. - To show the old ``{name}`` use ``{symbols::,}`` (this is the advanced formatting syntax employed by xkbgroup package) + For details on formatting see https://github.com/hcpl/xkbgroup/blob/master/docs/formatting.rst. * Now Xkblayout can switch groups and you can toggle groups with keyboard at the same time.
This commit is contained in:
parent
1d1491c6a3
commit
8f7a35ae92
@ -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:
|
||||||
|
@ -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,79 @@ 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"])``
|
||||||
|
|
||||||
|
.. 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)
|
|
||||||
|
Loading…
Reference in New Issue
Block a user