Merge branch 'master' into staging
[jackhill/guix/guix.git] / gnu / installer / newt / keymap.scm
index 219ac3f..2908ba7 100644 (file)
@@ -1,5 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2018 Mathieu Othacehe <m.othacehe@gmail.com>
+;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
   #:use-module (guix records)
   #:use-module (newt)
   #:use-module (srfi srfi-1)
+  #:use-module (srfi srfi-26)
   #:use-module (srfi srfi-34)
   #:use-module (srfi srfi-35)
-  #:export (run-keymap-page))
+  #:use-module (ice-9 i18n)
+  #:use-module (ice-9 match)
+  #:export (run-keymap-page
+            keyboard-layout->configuration))
 
 (define (run-layout-page layouts layout->text)
-  (let ((title (G_ "Layout selection")))
+  (let ((title (G_ "Layout")))
     (run-listbox-selection-page
      #:title title
      #:info-text (G_ "Please choose your keyboard layout.")
      #:listbox-items layouts
      #:listbox-item->text layout->text
-     #:button-text (G_ "Cancel")
+     #:sort-listbox-items? #f
+     #:button-text (G_ "Exit")
      #:button-callback-procedure
      (lambda _
        (raise
          (&installer-step-abort)))))))
 
 (define (run-variant-page variants variant->text)
-  (let ((title (G_ "Variant selection")))
+  (let ((title (G_ "Variant")))
     (run-listbox-selection-page
      #:title title
      #:info-text (G_ "Please choose a variant for your keyboard layout.")
      #:listbox-items variants
      #:listbox-item->text variant->text
-     #:button-text (G_ "Back")
-     #:button-callback-procedure
-     (lambda _
-       (raise
-        (condition
-         (&installer-step-abort)))))))
-
-(define (run-model-page models model->text)
-  (let ((title (G_ "Keyboard model selection")))
-    (run-listbox-selection-page
-     #:title title
-     #:info-text (G_ "Please choose your keyboard model.")
-     #:listbox-items models
-     #:listbox-item->text model->text
-     #:listbox-default-item (find (lambda (model)
-                                    (string=? (x11-keymap-model-name model)
-                                              "pc105"))
-                                  models)
      #:sort-listbox-items? #f
      #:button-text (G_ "Back")
      #:button-callback-procedure
         (condition
          (&installer-step-abort)))))))
 
-(define* (run-keymap-page #:key models layouts)
-  "Run a page asking the user to select a keyboard model, layout and
-variant. MODELS and LAYOUTS are lists of supported X11-KEYMAP-MODEL and
-X11-KEYMAP-LAYOUT. Return a list of three elements, the names of the selected
-keyboard model, layout and variant."
+(define (sort-layouts layouts)
+  "Sort LAYOUTS list by putting the US layout ahead and return it."
+  (define (layout<? layout1 layout2)
+    (let ((text1 (x11-keymap-layout-description layout1))
+          (text2 (x11-keymap-layout-description layout2)))
+      ;; XXX: We're calling 'gettext' more than once per item.
+      (string-locale<? (gettext text1 "xkeyboard-config")
+                       (gettext text2 "xkeyboard-config"))))
+
+  (define preferred
+    ;; Two-letter language tag for the preferred keyboard layout.
+    (or (getenv "LANGUAGE") "us"))
+
+  (call-with-values
+      (lambda ()
+        (partition
+         (lambda (layout)
+           ;; The 'synopsis' field is usually a language code (e.g., "en")
+           ;; while the 'name' field is a country code (e.g., "us").
+           (or (string=? (x11-keymap-layout-name layout) preferred)
+               (string=? (x11-keymap-layout-synopsis layout) preferred)))
+         layouts))
+    (lambda (main others)
+      (append (sort main layout<?)
+              (sort others layout<?)))))
+
+(define (sort-variants variants)
+  "Sort VARIANTS list by putting the international variant ahead and return it."
+  (call-with-values
+      (lambda ()
+        (partition
+         (lambda (variant)
+           (let ((name (x11-keymap-variant-name variant)))
+             (string=? name "altgr-intl")))
+         variants))
+    (cut append <> <>)))
+
+(define* (run-keymap-page layouts)
+  "Run a page asking the user to select a keyboard layout and variant. LAYOUTS
+is a list of supported X11-KEYMAP-LAYOUT. Return a list of two elements, the
+names of the selected keyboard layout and variant."
   (define keymap-steps
     (list
-     (installer-step
-      (id 'model)
-      (compute
-       (lambda _
-         ;; TODO: Understand why (run-model-page models x11-keymap-model-name)
-         ;; fails with: warning: possibly unbound variable
-         ;; `%x11-keymap-model-description-procedure.
-         (run-model-page models (lambda (model)
-                                  (x11-keymap-model-description
-                                   model))))))
      (installer-step
       (id 'layout)
       (compute
        (lambda _
-         (let* ((layout (run-layout-page
-                         layouts
-                         (lambda (layout)
-                           (x11-keymap-layout-description layout)))))
-           (if (null? (x11-keymap-layout-variants layout))
-               ;; Break if this layout does not have any variant.
-               (raise
-                (condition
-                 (&installer-step-break)))
-               layout)))))
+         (run-layout-page
+          (sort-layouts layouts)
+          (lambda (layout)
+            (gettext (x11-keymap-layout-description layout)
+                     "xkeyboard-config"))))))
      ;; Propose the user to select a variant among those supported by the
      ;; previously selected layout.
      (installer-step
       (id 'variant)
       (compute
-       (lambda (result)
-         (let ((variants (x11-keymap-layout-variants
-                          (result-step result 'layout))))
-           (run-variant-page variants
-                             (lambda (variant)
-                               (x11-keymap-variant-description
-                                variant)))))))))
+       (lambda (result _)
+         (let* ((layout (result-step result 'layout))
+                (variants (x11-keymap-layout-variants layout)))
+           ;; Return #f if the layout does not have any variant.
+           (and (not (null? variants))
+                (run-variant-page
+                 (sort-variants variants)
+                 (lambda (variant)
+                   (gettext (x11-keymap-variant-description variant)
+                            "xkeyboard-config"))))))))))
 
   (define (format-result result)
-    (let ((model (x11-keymap-model-name
-                  (result-step result 'model)))
-          (layout (x11-keymap-layout-name
+    (let ((layout (x11-keymap-layout-name
                    (result-step result 'layout)))
           (variant (and=> (result-step result 'variant)
                           (lambda (variant)
-                            (x11-keymap-variant-name variant)))))
-      (list model layout (or variant ""))))
+                            (gettext (x11-keymap-variant-name variant)
+                                     "xkeyboard-config")))))
+      (list layout (or variant ""))))
   (format-result
    (run-installer-steps #:steps keymap-steps)))
+
+(define (keyboard-layout->configuration keymap)
+  "Return the operating system configuration snippet to install KEYMAP."
+  (match keymap
+    ((name "")
+     `((keyboard-layout (keyboard-layout ,name))))
+    ((name variant)
+     `((keyboard-layout (keyboard-layout ,name ,variant))))))