diff mbox series

[bug#62101,v2] home: services: Add home-xmodmap-service-type.

Message ID 86edpox2zd.fsf@conses.eu
State New
Headers show
Series [bug#62101,v2] home: services: Add home-xmodmap-service-type. | expand

Commit Message

Miguel Ángel Moreno March 16, 2023, 1:03 p.m. UTC
* gnu/home/services/desktop.scm (home-xmodmap-service-type)
(home-xmodmap-configuration): New variables;
(xmodmap-shepherd-service)
(get-xmodmap-configuration)
(get-xmodmap-file)
(add-xmodmap-config-file)
(add-xmodmap-package): New procedures;
* doc/guix.texi (Desktop Services): Document it.
---
 doc/guix.texi                 | 51 +++++++++++++++++++++
 gnu/home/services/desktop.scm | 85 +++++++++++++++++++++++++++++++++++
 2 files changed, 136 insertions(+)

Comments

Ludovic Courtès March 16, 2023, 9:43 p.m. UTC | #1
Hi,

conses <contact@conses.eu> skribis:

> * gnu/home/services/desktop.scm (home-xmodmap-service-type)
> (home-xmodmap-configuration): New variables;
> (xmodmap-shepherd-service)
> (get-xmodmap-configuration)
> (get-xmodmap-file)
> (add-xmodmap-config-file)
> (add-xmodmap-package): New procedures;
> * doc/guix.texi (Desktop Services): Document it.

Overall LGTM, with minor issues:

> +The syntax for the expression grammar is quite straightforward.  You can
> +either provide a list of cons cells and strings like this:

I’d suggest avoiding the first sentence, because what looks
straightforward to someone might be intimidating to another.  We also
avoid jargon like “cons cell” in the manual.

What about something like this:

  The @code{key-map} field takes a list of objects, each of which is
  either a @dfn{statement} (a string) or an @dfn{assignment} (a pair of
  strings).  As an example, the snippet below configures the @kbd{mod4}
  key (???) such that it does XYZ, FIXME: finish sentence :-)

… where ‘key-map’ is IMO a better name for ‘config’.

> +Alternatively, there is a more Lisp-like configuration syntax via Scheme
> +symbols, lists, and vectors, that you can use like this:
> +
> +@lisp
> +(service home-xmodmap-service-type
> +         (home-xmodmap-configuration
> +          (config '((#(add mod4) . Print)
> +                    (clear lock)

I don’t find it very useful; I’d rather support only one syntax, but
clearly explained.  So my suggestion would be to drop this.

> +@item @code{config} (default: @code{config}) (type: list)

So this would be renamed to @code{key-map} maybe.

> +(define (get-xmodmap-configuration field-name val)

As a rule of thumb, you can drop ‘get-’ from procedure names; procedures
like this one are rarely called ‘get-SOMETHING’.

> +     (service-extension home-profile-service-type
> +                        add-xmodmap-package)

I believe this extension is unnecessary.

Could you send an updated patch?

Thank you!

Ludo’.
diff mbox series

Patch

diff --git a/doc/guix.texi b/doc/guix.texi
index 6671ba9305..c9ec781e8b 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -42541,6 +42541,57 @@  Desktop Home Services
 @end table
 @end deftp
 
+@defvar home-xmodmap-service-type
+This is the service type for the
+@uref{https://gitlab.freedesktop.org/xorg/app/xmodmap,xmodmap} utility
+to modify keymaps and pointer button mappings under the Xorg display
+server.  Its associated value must be a
+@code{home-xmodmap-configuration} record, as shown below.
+
+The syntax for the expression grammar is quite straightforward.  You can
+either provide a list of cons cells and strings like this:
+
+@lisp
+(service home-xmodmap-service-type
+         (home-xmodmap-configuration
+          (config '(("add mod4" . "Print")
+                    "clear lock"
+                    "clear control"
+                    ("keycode 66" . "Control_L")
+                    ("add control" . "Control_L Control_R")))))
+@end lisp
+
+Alternatively, there is a more Lisp-like configuration syntax via Scheme
+symbols, lists, and vectors, that you can use like this:
+
+@lisp
+(service home-xmodmap-service-type
+         (home-xmodmap-configuration
+          (config '((#(add mod4) . Print)
+                    (clear lock)
+                    (clear control)
+                    (#(keycode 66) . Control_L)
+                    (#(add control) . #(Control_L Control_R))))))
+@end lisp
+@end defvar
+
+@deftp {Data Type} home-xmodmap-configuration
+The configuration record for @code{home-xmodmap-service-type}.  Its
+available fields are:
+
+@table @asis
+@item @code{xmodmap} (default: @code{xmodmap}) (type: file-like)
+The @code{xmodmap} package to use.
+
+@item @code{config} (default: @code{config}) (type: list)
+The list of expressions to be placed in the
+@file{~/.config/xmodmap/config} configuration file and read on service
+startup.
+
+@end table
+@end deftp
+
+
 @node Guix Home Services
 @subsection Guix Home Services
 
diff --git a/gnu/home/services/desktop.scm b/gnu/home/services/desktop.scm
index cb25b03b64..8bc3d82cba 100644
--- a/gnu/home/services/desktop.scm
+++ b/gnu/home/services/desktop.scm
@@ -22,10 +22,12 @@  (define-module (gnu home services desktop)
   #:use-module (gnu home services shepherd)
   #:use-module (gnu services configuration)
   #:autoload   (gnu packages glib)    (dbus)
+  #:autoload   (gnu packages xorg) (setxkbmap xmodmap)
   #:autoload   (gnu packages xdisorg) (redshift)
   #:use-module (guix records)
   #:use-module (guix gexp)
   #:use-module (srfi srfi-1)
+  #:use-module (srfi srfi-43)
   #:use-module (ice-9 match)
   #:export (home-redshift-configuration
             home-redshift-configuration?
@@ -226,3 +228,86 @@  (define home-dbus-service-type
    (default-value (home-dbus-configuration))
    (description
     "Run the session-specific D-Bus inter-process message bus.")))
+
+
+;;;
+;;; xmodmap
+;;;
+
+(define-configuration/no-serialization home-xmodmap-configuration
+  (xmodmap
+   (file-like xmodmap)
+   "The @code{xmodmap} package to use.")
+  (config
+   (list '())
+   "List of expressions to be inserted in the @file{.config/xmodmap/config}
+configuration file."))
+
+(define (xmodmap-shepherd-service config)
+  (list
+   (shepherd-service
+    (provision '(xmodmap))
+    (start #~(make-system-constructor
+              (string-join
+               (list #$(file-append
+                        (home-xmodmap-configuration-xmodmap config)
+                        "/bin/xmodmap")
+                     #$(get-xmodmap-file config)))))
+    (stop #~(make-system-constructor
+             #$(file-append setxkbmap "/bin/setxkbmap")))
+    (documentation "On startup, run @code{xmodmap} and read the expressions in
+the configuration file.  On stop, reset all the mappings back to the
+defaults."))))
+
+(define (get-xmodmap-configuration field-name val)
+  (define serialize-term
+    (match-lambda
+      ((? vector? e)
+       (string-join
+        (vector-fold (lambda (_ acc e)
+                       (append acc (list (serialize-term e))))
+                     '() e)))
+      ((? symbol? e) (symbol->string e))
+      ((? number? e) (number->string e))
+      (e e)))
+
+  (define serialize-field
+    (match-lambda
+      ((? list? e)
+       (string-join (map serialize-term e)))
+      ((key . value)
+       (format #f "~a = ~a" (serialize-term key) (serialize-term value)))
+      (key (string-append (serialize-term key)))))
+
+  #~(string-append
+     #$@(interpose
+         (map serialize-field val)
+         "\n" 'suffix)))
+
+(define (get-xmodmap-file config)
+  (mixed-text-file
+   "config"
+   (get-xmodmap-configuration
+    #f (home-xmodmap-configuration-config config))))
+
+(define (add-xmodmap-config-file config)
+  `(("xmodmap/config"
+     ,(get-xmodmap-file config))))
+
+(define (add-xmodmap-package config)
+  (list (home-xmodmap-configuration-xmodmap config)))
+
+(define home-xmodmap-service-type
+  (service-type
+   (name 'home-xmodmap)
+   (extensions
+    (list
+     (service-extension home-profile-service-type
+                        add-xmodmap-package)
+     (service-extension home-xdg-configuration-files-service-type
+                        add-xmodmap-config-file)
+     (service-extension home-shepherd-service-type
+                        xmodmap-shepherd-service)))
+   (default-value (home-xmodmap-configuration))
+   (description "Run the @code{xmodmap} utility to modify keymaps and pointer
+buttons under the Xorg display server via user-defined expressions.")))