From 69da1807f02daa776472893741c2f82eca8e838d Mon Sep 17 00:00:00 2001 From: aszlig Date: Mon, 3 Jul 2017 08:14:19 +0200 Subject: nixos/xserver: Allow more than one keyboard layout Regression introduced by 44c64fef16ed566786c8db276085b484c9d233f3. 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 Fixes: #26961 Closes: #26984 --- nixos/modules/services/x11/xserver.nix | 52 +++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 16 deletions(-) (limited to 'nixos') diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix index 504a6b79d577..bb9704fc26f0 100644 --- a/nixos/modules/services/x11/xserver.nix +++ b/nixos/modules/services/x11/xserver.nix @@ -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 - - cat >&2 <<-EOF - - The selected keyboard layout definition does not exist: - - $layout + }' "$xkbDir/rules/base.lst" | sort -u + )" + + layoutNotFound() { + echo >&2 + echo "The following layouts and variants are available:" >&2 + echo >&2 + + # 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 + + 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 = -- cgit 1.4.1