nixos/xserver: Allow more than one keyboard layout

Regression introduced by 44c64fef16.

The services.xserver.layout option allows to specify more than one
layout separated by comma, which the commit above didn't take into
account.

This is very similar to @lheckemann's pull request (#26984) but differs
in the following ways:

  * Print out the full list available layouts (as suggested by @0xABAB
    in [1]).
  * Loop over $layout using the default IFS (and thus no need for
    escaping ${cfg.layout}), because the layouts won't contain white
    spaces.
  * Re-do the error message, which now uses multiple echos instead of a
    heredoc, so the line is wrapped according to the viewers terminal
    width.

I've tested this with several good and bad layouts and also against the
keymap NixOS VM subtests.

[1]: https://github.com/NixOS/nixpkgs/pull/26984#discussion_r125146700

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
Fixes: #26961
Closes: #26984
This commit is contained in:
aszlig 2017-07-03 08:14:19 +02:00
parent d97cdfc591
commit 69da1807f0
No known key found for this signature in database
GPG key ID: 1DE8E48E57DB5436

View file

@ -651,29 +651,49 @@ in
system.extraDependencies = singleton (pkgs.runCommand "xkb-layouts-exist" {
inherit (cfg) layout xkbDir;
} ''
if sed -n -e ':i /^! \(layout\|variant\) *$/ {
# We can use the default IFS here, because the layouts won't contain
# spaces or tabs and are ruled out by the sed expression below.
availableLayouts="$(
sed -n -e ':i /^! \(layout\|variant\) *$/ {
# Loop through all of the layouts/variants until we hit another ! at
# the start of the line or the line is empty ('t' branches only if
# the last substitution was successful, so if the line is empty the
# substition will fail).
:l; n; /^!/bi; s/^ *\([^ ]\+\).*/\1/p; tl
}' "$xkbDir/rules/base.lst" | grep -qxF "$layout"
then
touch "$out"
exit 0
fi
}' "$xkbDir/rules/base.lst" | sort -u
)"
cat >&2 <<-EOF
layoutNotFound() {
echo >&2
echo "The following layouts and variants are available:" >&2
echo >&2
The selected keyboard layout definition does not exist:
# While an output width of 80 is more desirable for small terminals, we
# really don't know the amount of columns of the terminal from within
# the builder. The content in $availableLayouts however is pretty
# large, so let's opt for a larger width here, because it will print a
# smaller amount of lines on modern KMS/framebuffer terminals and won't
# lose information even in smaller terminals (it only will look a bit
# ugly).
echo "$availableLayouts" | ${pkgs.utillinux}/bin/column -c 150 >&2
$layout
echo >&2
echo "However, the keyboard layout definition in" \
"\`services.xserver.layout' contains the layout \`$1', which" \
"isn't a valid layout or variant." >&2
echo >&2
exit 1
}
Set \`services.xserver.layout' to the name of an existing keyboard
layout (check $xkbDir/rules/base.lst for options).
# Again, we don't need to take care of IFS, see the comment for
# $availableLayouts.
for l in ''${layout//,/ }; do
if ! echo "$availableLayouts" | grep -qxF "$l"; then
layoutNotFound "$l"
fi
done
EOF
exit 1
touch "$out"
'');
services.xserver.config =