~ruther/guix-local

69d051f715fc2f2f56543edba22bae50bdcb36dd — Efraim Flashner 3 years ago c7eed71
home: Add inputrc service.

* gnu/home/services/shells.scm (home-inputrc-service-type,
home-inputrc-configuration): New variables.
(serialize-inputrc-key-bindings, serialize-inputrc-variables,
serialize-inputrc-conditional-constructs,
serialize-inputrc-extra-content): New procedures.
* doc/guix.texi (Shells Home Services): Document it.
2 files changed, 262 insertions(+), 1 deletions(-)

M doc/guix.texi
M gnu/home/services/shells.scm
M doc/guix.texi => doc/guix.texi +129 -0
@@ 42991,6 42991,135 @@ for example).

@end deftp

@subsubheading Inputrc Profile Service
@cindex inputrc
@cindex readline

The @uref{https://tiswww.cwru.edu/php/chet/readline/rltop.html, GNU
Readline package} includes Emacs and vi editing modes, with the ability
to customize the configuration with settings in the @file{~/.inputrc}
file.  With the @code{gnu home services shells} module, you can setup
your readline configuration in a predictable manner, as shown below.
For more information about configuring an @file{~/.inputrc} file,
@pxref{Readline Init File,,, readline, GNU Readline}.

@defvar home-inputrc-service-type

This is the service to setup various @file{.inputrc} configurations. The
settings in @file{.inputrc} are read by all programs which are linked
with GNU Readline.

Here is an example of a service and its configuration that you could add
to the @code{services} field of your @code{home-environment}:

@lisp
(service home-inputrc-service-type
         (home-inputrc-configuration
           (key-bindings
            `(("Control-l" . "clear-screen")))
           (variables
            `(("bell-style" . "visible")
              ("colored-completion-prefix" . #t)
              ("editing-mode" . "vi")
              ("show-mode-in-prompt" . #t)))
           (conditional-constructs
            `(("$if mode=vi" .
               ,(home-inputrc-configuration
                  (variables
                   `(("colored-stats" . #t)
                     ("enable-bracketed-paste" . #t)))))
              ("$else" .
               ,(home-inputrc-configuration
                  (variables
                   `(("show-all-if-ambiguous" . #t)))))
              ("endif" . #t)
              ("$include" . "/etc/inputrc")
              ("$include" . ,(file-append
                               (specification->package "readline")
                               "/etc/inputrc"))))))
@end lisp

The example above starts with a combination of @code{key-bindings} and
@code{variables}.  The @code{conditional-constructs} show how it is
possible to add conditionals and includes.  In the example above
@code{colored-stats} is only enabled if the editing mode is @code{vi}
style, and it also reads any additional configuration located in
@file{/etc/inputrc} or in @file{/gnu/store/@dots{}-readline/etc/inputrc}.

The value associated with a @code{home-inputrc-service-type} instance
must be a @code{home-inputrc-configuration} record, as described below.

@end defvar

@anchor{home-inputrc-configuration}
@deftp {Data Type} home-inputrc-configuration
Available @code{home-inputrc-configuration} fields are:

@table @asis
@item @code{key-bindings} (default: @code{'()}) (type: alist)
Association list of readline key bindings to be added to the
@file{~/.inputrc} file.

@lisp
'((\"Control-l\" . \"clear-screen\"))
@end lisp

turns into

@example
Control-l: clear-screen
@end example

@item @code{variables} (default: @code{'()}) (type: alist)
Association list of readline variables to set.

@lisp
'((\"bell-style\" . \"visible\")
  (\"colored-completion-prefix\" . #t))
@end lisp

turns into

@example
set bell-style visible
set colored-completion-prefix on
@end example

@item @code{conditional-constructs} (default: @code{'()}) (type: alist)
Association list of conditionals to add to the initialization file.  This
includes @command{$if}, @command{else}, @command{endif} and @command{include}
and they receive a value of another @command{home-inputrc-configuration}.

@lisp
(conditional-constructs
 `((\"$if mode=vi\" .
     ,(home-inputrc-configuration
        (variables
         `((\"show-mode-in-prompt\" . #t)))))
   (\"$else\" .
     ,(home-inputrc-configuration
        (key-bindings
         `((\"Control-l\" . \"clear-screen\")))))
   (\"$endif\" . #t)))
@end lisp

turns into

@example
$if mode=vi
set show-mode-in-prompt on
$else
Control-l: clear-screen
$endif
@end example

@item @code{extra-content} (default: @code{""}) (type: text-config)
Extra content appended as-is to the configuration file.  Run @command{man
readline} for more information about all the configuration options.

@end table
@end deftp

@node Mcron Home Service
@subsection Scheduled User's Job Execution


M gnu/home/services/shells.scm => gnu/home/services/shells.scm +133 -1
@@ 1,6 1,7 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2021 Andrew Tropin <andrew@trop.in>
;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz>
;;; Copyright © 2023 Efraim Flashner <efraim@flashner.co.il>
;;;
;;; This file is part of GNU Guix.
;;;


@@ 44,7 45,10 @@

            home-fish-service-type
            home-fish-configuration
            home-fish-extension))
            home-fish-extension

            home-inputrc-service-type
            home-inputrc-configuration))

;;; Commentary:
;;;


@@ 626,6 630,134 @@ end\n\n")
                (description "\
Install and configure Fish, the friendly interactive shell.")))


;;;
;;; Readline.
;;;

(define (serialize-inputrc-key-bindings field-name val)
  #~(string-append
     #$@(map
         (match-lambda
           ((key . value)
            #~(string-append #$key ": " #$value "\n")))
         val)))

(define (serialize-inputrc-variables field-name val)
  #~(string-append
     #$@(map
         (match-lambda
           ((key . #f)
            #~(string-append "set " #$key " off\n"))
           ((key . #t)
            #~(string-append "set " #$key " on\n"))
           ((key . value)
            #~(string-append "set " #$key " " #$value "\n")))
         val)))

(define (serialize-inputrc-conditional-constructs field-name val)
  #~(string-append
     #$@(map
         (match-lambda
           (("$endif" . _)
            "$endif\n")
           (("$include" . value)
            #~(string-append "$include " #$value "\n"))
           ;; TODO: key can only be "$if" or "$else".
           ((key . value)
            #~(string-append #$key "\n"
                             #$(serialize-configuration
                                 value
                                 home-inputrc-configuration-fields))))
         val)))

(define (serialize-inputrc-extra-content field-name value)
  #~(if (string=? #$value "") "" (string-append #$value "\n")))

(define-configuration home-inputrc-configuration
  (key-bindings
   (alist '())
   "Association list of readline key bindings to be added to the
@code{~/.inputrc} file.  This is where code like this:

@lisp
'((\"Control-l\" . \"clear-screen\"))
@end lisp

turns into

@example
Control-l: clear-screen
@end example"
   (serializer serialize-inputrc-key-bindings))
  (variables
   (alist '())
   "Association list of readline variables to set.  This is where configuration
options like this:

@lisp
'((\"bell-style\" . \"visible\")
  (\"colored-completion-prefix\" . #t))
@end lisp

turns into

@example
set bell-style visible
set colored-completion-prefix on
@end example"
   (serializer serialize-inputrc-variables))
  (conditional-constructs
   (alist '())
   "Association list of conditionals to add to the initialization file.  This
includes @command{$if}, @command{else}, @command{endif} and @command{include}
and they receive a value of another @command{home-inputrc-configuration}.

@lisp
(conditional-constructs
 `((\"$if mode=vi\" .
     ,(home-inputrc-configuration
        (variables
         `((\"show-mode-in-prompt\" . #t)))))
   (\"$else\" .
     ,(home-inputrc-configuration
        (key-bindings
         `((\"Control-l\" . \"clear-screen\")))))
   (\"$endif\" . #t)))
@end lisp

turns into

@example
$if mode=vi
set show-mode-in-prompt on
$else
Control-l: clear-screen
$endif
@end example"
   (serializer serialize-inputrc-conditional-constructs))
  (extra-content
   (string "")
   "Extra content appended as-is to the configuration file.  Run @command{man
readline} for more information about all the configuration options."
   (serializer serialize-inputrc-extra-content)))

(define (home-inputrc-files config)
  (list
   `(".inputrc"
     ,(mixed-text-file "inputrc"
                       (serialize-configuration
                         config
                         home-inputrc-configuration-fields)))))

(define home-inputrc-service-type
  (service-type (name 'inputrc)
                (extensions
                 (list (service-extension home-files-service-type
                                          home-inputrc-files)))
                (default-value (home-inputrc-configuration))
                (description "Configure readline in @code{.inputrc}.")))


(define (generate-home-shell-profile-documentation)
  (generate-documentation