Subject: [bug#34929] [PATCH 04/12] bootloader: Add a 'keyboard-layout' field.

From: Ludovic Courtès <[email-masked]>
Date: Thu, 21 Mar 2019 00:04:27 +0100

* gnu/bootloader/grub.scm (keyboard-layout-file): New procedure.
(grub-configuration-file)[keyboard-layout-file]: New variable.
[builder]: Use it.
* gnu/bootloader.scm (<bootloader-configuration>)[keyboard-layout]: New
field.
* doc/guix.texi (Bootloader Configuration): Document it.

Co-authored-by: nee <[email-masked]>
---
 doc/guix.texi           | 28 ++++++++++++++++++++++++++++
 gnu/bootloader.scm      |  3 +++
 gnu/bootloader/grub.scm | 35 +++++++++++++++++++++++++++++++++++
 3 files changed, 66 insertions(+)

diff --git a/doc/guix.texi b/doc/guix.texi
index 63581bbe41..c687f78eac 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -23134,6 +23134,34 @@ current system.
 The number of seconds to wait for keyboard input before booting.  Set to
 0 to boot immediately, and to -1 to wait indefinitely.
 
+@cindex keyboard layout, for the bootloader
+@item @code{keyboard-layout} (default: @code{#f})
+If this is @code{#f}, the bootloader's menu (if any) uses the default keyboard
+layout, usually US@tie{}English (``qwerty'').
+
+Otherwise, this must be a @code{keyboard-layout} object.  For instance, the
+following example defines a standard German keyboard layout:
+
+@example
+(keyboard-layout "de")
+@end example
+
+@noindent
+while the example below designates the bépo layout for French:
+
+@example
+(keyboard-layout "fr" "bepo")
+@end example
+
+The layout name and variant must match an existing layout in the
+@code{xkeyboard-config} package under the @file{share/X11/xkb/symbols}
+directory.
+
+@quotation Note
+This option is currently ignored by bootloaders other than @code{grub} and
+@code{grub-efi}.
+@end quotation
+
 @item @code{theme} (default: @var{#f})
 The bootloader theme object describing the theme to use.  If no theme
 is provided, some bootloaders might use a default theme, that's true
diff --git a/gnu/bootloader.scm b/gnu/bootloader.scm
index e48bcc073c..e7f7331dd8 100644
--- a/gnu/bootloader.scm
+++ b/gnu/bootloader.scm
@@ -47,6 +47,7 @@
             bootloader-configuration-menu-entries
             bootloader-configuration-default-entry
             bootloader-configuration-timeout
+            bootloader-configuration-keyboard-layout
             bootloader-configuration-theme
             bootloader-configuration-terminal-outputs
             bootloader-configuration-terminal-inputs
@@ -113,6 +114,8 @@
                       (default 0))
   (timeout            bootloader-configuration-timeout ;seconds as integer
                       (default 5))
+  (keyboard-layout    bootloader-configuration-keyboard-layout ;string | #f
+                      (default #f))
   (theme              bootloader-configuration-theme ;bootloader-specific theme
                       (default #f))
   (terminal-outputs   bootloader-configuration-terminal-outputs ;list of symbols
diff --git a/gnu/bootloader/grub.scm b/gnu/bootloader/grub.scm
index 14aede72c5..e97a17b3e2 100644
--- a/gnu/bootloader/grub.scm
+++ b/gnu/bootloader/grub.scm
@@ -27,8 +27,10 @@
   #:use-module (gnu bootloader)
   #:use-module (gnu system uuid)
   #:use-module (gnu system file-systems)
+  #:use-module (gnu system keyboard)
   #:autoload   (gnu packages bootloaders) (grub)
   #:autoload   (gnu packages gtk) (guile-cairo guile-rsvg)
+  #:autoload   (gnu packages xorg) (xkeyboard-config)
   #:use-module (ice-9 match)
   #:use-module (ice-9 regex)
   #:use-module (srfi srfi-1)
@@ -219,6 +221,26 @@ fi~%"
 ;;; Configuration file.
 ;;;
 
+(define* (keyboard-layout-file layout
+                               #:key
+                               (grub grub))
+  "Process the X keyboard layout description LAYOUT, a <keyboard-layout> record,
+and return a file in the format for GRUB keymaps.  LAYOUT must be present in
+the 'share/X11/xkb/symbols/' directory of 'xkeyboard-config'."
+  (define builder
+    (with-imported-modules '((guix build utils))
+      #~(begin
+          (use-modules (guix build utils))
+
+          ;; 'grub-kbdcomp' passes all its arguments but '-o' to 'ckbcomp'
+          ;; (from the 'console-setup' package).
+          (invoke #$(file-append grub "/bin/grub-mklayout")
+                  "-i" #+(keyboard-layout->console-keymap layout)
+                  "-o" #$output))))
+
+  (computed-file (string-append "grub-keymap." (keyboard-layout-name layout))
+                 builder))
+
 (define (grub-setup-io config)
   "Return GRUB commands to configure the input / output interfaces.  The result
 is a string that can be inserted in grub.cfg."
@@ -330,6 +352,18 @@ entries corresponding to old generations of the system."
                #:system system
                #:port #~port))
 
+  (define keyboard-layout-config
+    (let ((layout (bootloader-configuration-keyboard-layout config))
+          (grub   (bootloader-package
+                   (bootloader-configuration-bootloader config))))
+      #~(let ((keymap #$(and layout
+                             (keyboard-layout-file layout #:grub grub))))
+          (when keymap
+            (format port "\
+terminal_input at_keyboard
+insmod keylayouts
+keymap ~a~%" keymap)))))
+
   (define builder
     #~(call-with-output-file #$output
         (lambda (port)
@@ -338,6 +372,7 @@ entries corresponding to old generations of the system."
 # will be lost upon reconfiguration.
 ")
           #$sugar
+          #$keyboard-layout-config
           (format port "
 set default=~a
 set timeout=~a~%"
-- 
2.21.0