Subject: [bug#55752] [PATCH 2/5] guix system: Add 'edit' sub-command.

From: Ludovic Courtès <[email-masked]>
Date: Wed, 1 Jun 2022 17:42:59 +0200

* guix/scripts/system/edit.scm: New file.
* Makefile.am (MODULES): Add it.
* guix/scripts/system.scm (show-help): Mention "edit".
(actions): Add it.
(process-command): Handle it.
* doc/guix.texi (Invoking guix system): Document it.
* po/guix/POTFILES.in: Add guix/scripts/system/edit.scm.
---
 Makefile.am                  |  3 +-
 doc/guix.texi                | 13 ++++++++
 guix/scripts/system.scm      |  7 +++-
 guix/scripts/system/edit.scm | 64 ++++++++++++++++++++++++++++++++++++
 po/guix/POTFILES.in          |  1 +
 5 files changed, 86 insertions(+), 2 deletions(-)
 create mode 100644 guix/scripts/system/edit.scm

diff --git a/Makefile.am b/Makefile.am
index 968bde8131..f585d00b86 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -308,8 +308,9 @@ MODULES =					\
   guix/scripts/describe.scm			\
   guix/scripts/style.scm			\
   guix/scripts/system.scm			\
-  guix/scripts/system/search.scm		\
+  guix/scripts/system/edit.scm			\
   guix/scripts/system/reconfigure.scm		\
+  guix/scripts/system/search.scm		\
   guix/scripts/home.scm			\
   guix/scripts/home/import.scm			\
   guix/scripts/lint.scm				\
diff --git a/doc/guix.texi b/doc/guix.texi
index 88e009fe7c..ecd99084ef 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -36617,6 +36617,19 @@ As for @command{guix package --search}, the result is written in
 @code{recutils} format, which makes it easy to filter the output
 (@pxref{Top, GNU recutils databases,, recutils, GNU recutils manual}).
 
+@cindex service type definition, editing
+@cindex editing, service type definition
+@item edit
+Edit or view the definition of the given service types.
+
+For example, the command below opens your editor, as specified by the
+@env{EDITOR} environment variable, on the definition of the
+@code{openssh} service type:
+
+@example
+guix system edit openssh
+@end example
+
 @item reconfigure
 Build the operating system described in @var{file}, activate it, and
 switch to it@footnote{This action (and the related actions
diff --git a/guix/scripts/system.scm b/guix/scripts/system.scm
index eaa245eb44..261a1d226d 100644
--- a/guix/scripts/system.scm
+++ b/guix/scripts/system.scm
@@ -944,6 +944,8 @@ (define (show-help)
   (newline)
   (display (G_ "\
    search           search for existing service types\n"))
+  (display (G_ "\
+   edit             edit the definition of an existing service type\n"))
   (display (G_ "\
    reconfigure      switch to a new operating system configuration\n"))
   (display (G_ "\
@@ -1172,7 +1174,8 @@ (define actions '("build" "container" "vm" "vm-image" "image" "disk-image"
                   "extension-graph" "shepherd-graph"
                   "list-generations" "describe"
                   "delete-generations" "roll-back"
-                  "switch-generation" "search" "docker-image"))
+                  "switch-generation" "search" "edit"
+                  "docker-image"))
 
 (define (process-action action args opts)
   "Process ACTION, a sub-command, with the arguments are listed in ARGS.
@@ -1340,6 +1343,8 @@ (define-syntax-rule (with-store* store exp ...)
         (display-system-generation generation))))
     ((search)
      (apply (resolve-subcommand "search") args))
+    ((edit)
+     (apply (resolve-subcommand "edit") args))
     ;; The following commands need to use the store, but they do not need an
     ;; operating system configuration file.
     ((delete-generations)
diff --git a/guix/scripts/system/edit.scm b/guix/scripts/system/edit.scm
new file mode 100644
index 0000000000..d966ee0aaa
--- /dev/null
+++ b/guix/scripts/system/edit.scm
@@ -0,0 +1,64 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2022 Ludovic Courtès <[email-masked]>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix is free software; you can redistribute it and/or modify it
+;;; under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (guix scripts system edit)
+  #:use-module (guix diagnostics)
+  #:use-module (guix i18n)
+  #:use-module (guix ui)
+  #:autoload   (guix utils) (string-closest)
+  #:use-module (gnu services)
+  #:use-module (srfi srfi-1)
+  #:use-module (ice-9 match)
+  #:autoload   (guix scripts edit) (spawn-editor)
+  #:export (guix-system-edit))
+
+(define (service-type-not-found type)
+  "Report an error about @var{type} not being found and exit."
+  (report-error (G_ "~a: no such service type~%") type)
+
+  (let* ((type      (symbol->string type))
+         (available (fold-service-types (lambda (type lst)
+                                          (cons (symbol->string
+                                                 (service-type-name type))
+                                                lst))
+                                        '()))
+         (closest   (string-closest type available)))
+    (unless (or (not closest) (string=? closest type))
+      (display-hint (format #f (G_ "Did you mean @code{~a}?~%")
+                            closest))))
+
+  (exit 1))
+
+
+(define (guix-system-edit . args)
+  (when (null? args)
+    (leave (G_ "no service types specified, nothing to edit~%")))
+
+  (let* ((types (append-map (lambda (type)
+                              (let ((type (string->symbol type)))
+                                (match (lookup-service-types type)
+                                  (() (service-type-not-found type))
+                                  ((one) (list one))
+                                  (lst
+                                   (warning (N_ "~a: ~a matching service type~%"
+                                                "~a: ~a matching service types~%"
+                                                (length lst))
+                                            type (length lst))
+                                   lst))))
+                            args)))
+    (spawn-editor (filter-map service-type-location types))))
diff --git a/po/guix/POTFILES.in b/po/guix/POTFILES.in
index 49a8edfef3..5ad3c9f0a8 100644
--- a/po/guix/POTFILES.in
+++ b/po/guix/POTFILES.in
@@ -87,6 +87,7 @@ guix/scripts/pull.scm
 guix/scripts/substitute.scm
 guix/scripts/authenticate.scm
 guix/scripts/system.scm
+guix/scripts/system/edit.scm
 guix/scripts/system/search.scm
 guix/scripts/lint.scm
 guix/scripts/publish.scm
-- 
2.36.1