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 + }' "$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 =