From 5f8adea86cac1e0b126b181a4d3cc67c0503f43b Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Thu, 14 Jul 2022 01:04:59 +0200 Subject: doc: Add example of 'bash-extension'. * doc/guix.texi (Shells Home Services): Add 'bash-extension' example. --- doc/guix.texi | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'doc') diff --git a/doc/guix.texi b/doc/guix.texi index a7ac74b416..8b09bcd4eb 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -39663,6 +39663,23 @@ contents of the extensions will be added to the end of the corresponding Bash configuration files (@pxref{Bash Startup Files,,, bash, The GNU Bash Reference Manual}. +For example, here is how you would define a service that extends the +Bash service such that @file{~/.bash_profile} defines an additional +environment variable, @env{PS1}: + +@lisp +(define bash-fancy-prompt-service + (simple-service 'bash-fancy-prompt + home-bash-service-type + (home-bash-extension + (environment-variables + '(("PS1" . "\\u \\wλ ")))))) +@end lisp + +You would then add @code{bash-fancy-prompt-service} to the list in the +@code{services} field of your @code{home-environment}. The reference of +@code{home-bash-extension} follows. + @deftp {Data Type} home-bash-extension Available @code{home-bash-extension} fields are: -- cgit v1.2.3 From 4ce7f1fb24a111f3e92d5b889d1271bebf109d09 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Fri, 15 Jul 2022 17:27:08 +0200 Subject: monad-repl: Add "build", "lower", and "verbosity" commands. Fixes . Reported by Maxime Devos . * guix/monad-repl.scm (%build-verbosity): New variable. (evaluate/print-with-store): New procedure. (run-in-store): Rewrite in terms of 'evaluate/print-with-store'. (verbosity, lower, build): New meta-commands. * doc/guix.texi (Using Guix Interactively): New node. (The Store Monad): Link to it. (Invoking guix repl): Likewise. * doc/contributing.texi (Running Guix Before It Is Installed): Refer to it. (The Perfect Setup): Suggest 'guix install' rather than 'guix package -i'. --- doc/contributing.texi | 5 +- doc/guix.texi | 137 ++++++++++++++++++++++++++++++++++++++++++++++++-- guix/monad-repl.scm | 64 ++++++++++++++++++++--- 3 files changed, 192 insertions(+), 14 deletions(-) (limited to 'doc') diff --git a/doc/contributing.texi b/doc/contributing.texi index 6a2564b07d..ad312ddeb6 100644 --- a/doc/contributing.texi +++ b/doc/contributing.texi @@ -225,8 +225,7 @@ $ ./pre-inst-env guile -c '(use-modules (guix utils)) (pk (%current-system))' @noindent @cindex REPL @cindex read-eval-print loop -@dots{} and for a REPL (@pxref{Using Guile Interactively,,, guile, Guile -Reference Manual}): +@dots{} and for a REPL (@pxref{Using Guix Interactively}): @example $ ./pre-inst-env guile @@ -292,7 +291,7 @@ Manual}). First, you need more than an editor, you need wonderful @url{https://nongnu.org/geiser/, Geiser}. To set that up, run: @example -guix package -i emacs guile emacs-geiser emacs-geiser-guile +guix install emacs guile emacs-geiser emacs-geiser-guile @end example Geiser allows for interactive and incremental development from within diff --git a/doc/guix.texi b/doc/guix.texi index 8b09bcd4eb..8fc8f53d0e 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -299,6 +299,7 @@ Programming Interface * The Store Monad:: Purely functional interface to the store. * G-Expressions:: Manipulating build expressions. * Invoking guix repl:: Programming Guix in Guile. +* Using Guix Interactively:: Fine-grain interaction at the REPL. Defining Packages @@ -7100,6 +7101,7 @@ package definitions. * The Store Monad:: Purely functional interface to the store. * G-Expressions:: Manipulating build expressions. * Invoking guix repl:: Programming Guix in Guile +* Using Guix Interactively:: Fine-grain interaction at the REPL. @end menu @node Package Modules @@ -10860,8 +10862,9 @@ So, to exit the monad and get the desired effect, one must use @end lisp Note that the @code{(guix monad-repl)} module extends the Guile REPL with -new ``meta-commands'' to make it easier to deal with monadic procedures: -@code{run-in-store}, and @code{enter-store-monad}. The former is used +new ``commands'' to make it easier to deal with monadic procedures: +@code{run-in-store}, and @code{enter-store-monad} (@pxref{Using Guix +Interactively}). The former is used to ``run'' a single monadic value through the store: @example @@ -10886,6 +10889,9 @@ scheme@@(guile-user)> Note that non-monadic values cannot be returned in the @code{store-monad} REPL. +Other meta-commands are available at the REPL, such as @code{,build} to +build a file-like object (@pxref{Using Guix Interactively}). + The main syntactic forms to deal with monads in general are provided by the @code{(guix monads)} module and are described below. @@ -11778,7 +11784,8 @@ lines at the top of the script: @code{!#} @end example -Without a file name argument, a Guile REPL is started: +Without a file name argument, a Guile REPL is started, allowing for +interactive use (@pxref{Using Guix Interactively}): @example $ guix repl @@ -11834,6 +11841,130 @@ Inhibit loading of the @file{~/.guile} file. By default, that configuration file is loaded when spawning a @code{guile} REPL. @end table +@node Using Guix Interactively +@section Using Guix Interactively + +The @command{guix repl} command gives you access to a warm and friendly +@dfn{read-eval-print loop} (REPL) (@pxref{Invoking guix repl}). If +you're getting into Guix programming---defining your own packages, +writing manifests, defining services for Guix System or Guix Home, +etc.---you will surely find it convenient to toy with ideas at the REPL. + +If you use Emacs, the most convenient way to do that is with Geiser +(@pxref{The Perfect Setup}), but you do not have to use Emacs to enjoy +the REPL@. When using @command{guix repl} or @command{guile} in the +terminal, we recommend using Readline for completion and Colorized to +get colorful output. To do that, you can run: + +@example +guix install guile guile-readline guile-colorized +@end example + +@noindent +... and then create a @file{.guile} in your home directory containing +this: + +@lisp +(use-modules (ice-9 readline) (ice-9 colorized)) + +(activate-readline) +(activate-colorized) +@end lisp + +The REPL lets you evaluate Scheme code; you type a Scheme expression at +the prompt, and the REPL prints what it evaluates to: + +@example +$ guix repl +scheme@@(guix-user)> (+ 2 3) +$1 = 5 +scheme@@(guix-user)> (string-append "a" "b") +$2 = "ab" +@end example + +It becomes interesting when you start fiddling with Guix at the REPL. +The first thing you'll want to do is to ``import'' the @code{(guix)} +module, which gives access to the main part of the programming +interface, and perhaps a bunch of useful Guix modules. You could type +@code{(use-modules (guix))}, which is valid Scheme code to import a +module (@pxref{Using Guile Modules,,, guile, GNU Guile Reference +Manual}), but the REPL provides the @code{use} @dfn{command} as a +shorthand notation (@pxref{REPL Commands,,, guile, GNU Guile Reference +Manual}): + +@example +scheme@@(guix-user)> ,use (guix) +scheme@@(guix-user)> ,use (gnu packages base) +@end example + +Notice that REPL commands are introduced by a leading comma. A REPL +command like @code{use} is not valid Scheme code; it's interpreted +specially by the REPL. + +Guix extends the Guile REPL with additional commands for convenience. +Among those, the @code{build} command comes in handy: it ensures that +the given file-like object is built, building it if needed, and returns +its output file name(s). In the example below, we build the +@code{coreutils} and @code{grep} packages, as well as a ``computed +file'' (@pxref{G-Expressions, @code{computed-file}}), and we use the +@code{scandir} procedure to list the files in Grep's @code{/bin} +directory: + +@example +scheme@@(guix-user)> ,build coreutils +$1 = "/gnu/store/@dots{}-coreutils-8.32-debug" +$2 = "/gnu/store/@dots{}-coreutils-8.32" +scheme@@(guix-user)> ,build grep +$3 = "/gnu/store/@dots{}-grep-3.6" +scheme@@(guix-user)> ,build (computed-file "x" #~(mkdir #$output)) +building /gnu/store/@dots{}-x.drv... +$4 = "/gnu/store/@dots{}-x" +scheme@@(guix-user)> ,use(ice-9 ftw) +scheme@@(guix-user)> (scandir (string-append $3 "/bin")) +$5 = ("." ".." "egrep" "fgrep" "grep") +@end example + +At a lower-level, a useful command is @code{lower}: it takes a file-like +object and ``lowers'' it into a derivation (@pxref{Derivations}) or a +store file: + +@example +scheme@@(guix-user)> ,lower grep +$6 = # /gnu/store/@dots{}-grep-3.6 7f0e639115f0> +scheme@@(guix-user)> ,lower (plain-file "x" "Hello!") +$7 = "/gnu/store/@dots{}-x" +@end example + +The full list of REPL commands can be seen by typing @code{,help guix} +and is given below for reference. + +@deffn {REPL command} build @var{object} +Lower @var{object} and build it if it's not already built, returning its +output file name(s). +@end deffn + +@deffn {REPL command} lower @var{object} +Lower @var{object} into a derivation or store file name and return it. +@end deffn + +@deffn {REPL command} verbosity @var{level} +Change build verbosity to @var{level}. + +This is similar to the @option{--verbosity} command-line option +(@pxref{Common Build Options}): level 0 means total silence, level 1 +shows build events only, and higher levels print build logs. +@end deffn + +@deffn {REPL command} run-in-store @var{exp} +Run @var{exp}, a monadic expresssion, through the store monad. +@xref{The Store Monad}, for more information. +@end deffn + +@deffn {REPL command} enter-store-monad +Enter a new REPL to evaluate monadic expressions (@pxref{The Store +Monad}). You can quit this ``inner'' REPL by typing @code{,q}. +@end deffn + @c ********************************************************************* @node Utilities @chapter Utilities diff --git a/guix/monad-repl.scm b/guix/monad-repl.scm index aefabdeebb..8a6053edd5 100644 --- a/guix/monad-repl.scm +++ b/guix/monad-repl.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2014, 2015, 2016 Ludovic Courtès +;;; Copyright © 2014, 2015, 2016, 2022 Ludovic Courtès ;;; ;;; This file is part of GNU Guix. ;;; @@ -21,6 +21,12 @@ #:use-module (guix monads) #:use-module (guix utils) #:use-module (guix packages) + #:use-module (guix status) + #:autoload (guix gexp) (lower-object) + #:use-module ((guix derivations) + #:select (derivation? + derivation->output-paths built-derivations)) + #:use-module (ice-9 match) #:use-module (ice-9 pretty-print) #:use-module (system repl repl) #:use-module (system repl common) @@ -69,16 +75,58 @@ #:guile-for-build guile) 'store-monad))) +(define %build-verbosity + ;; Current build verbosity level. + 1) + +(define* (evaluate/print-with-store mvalue #:key build?) + "Run monadic value MVALUE in the store monad and print its value." + (with-store store + (set-build-options store + #:print-build-trace #t + #:print-extended-build-trace? #t + #:multiplexed-build-output? #t) + (with-status-verbosity %build-verbosity + (let* ((guile (or (%guile-for-build) + (default-guile-derivation store))) + (values (run-with-store store + (if build? + (mlet %store-monad ((obj mvalue)) + (if (derivation? obj) + (mbegin %store-monad + (built-derivations (list obj)) + (return + (match (derivation->output-paths obj) + (((_ . files) ...) files)))) + (return (list obj)))) + (mlet %store-monad ((obj mvalue)) + (return (list obj)))) + #:guile-for-build guile))) + (for-each (lambda (value) + (run-hook before-print-hook value) + (pretty-print value)) + values))))) + (define-meta-command ((run-in-store guix) repl (form)) "run-in-store EXP Run EXP through the store monad." - (with-store store - (let* ((guile (or (%guile-for-build) - (default-guile-derivation store))) - (value (run-with-store store (repl-eval repl form) - #:guile-for-build guile))) - (run-hook before-print-hook value) - (pretty-print value)))) + (evaluate/print-with-store (repl-eval repl form))) + +(define-meta-command ((verbosity guix) repl (level)) + "verbosity LEVEL +Change build verbosity to LEVEL." + (set! %build-verbosity (repl-eval repl level))) + +(define-meta-command ((lower guix) repl (form)) + "lower OBJECT +Lower OBJECT into a derivation or store file and return it." + (evaluate/print-with-store (lower-object (repl-eval repl form)))) + +(define-meta-command ((build guix) repl (form)) + "build OBJECT +Lower OBJECT and build it, returning its output file name(s)." + (evaluate/print-with-store (lower-object (repl-eval repl form)) + #:build? #t)) (define-meta-command ((enter-store-monad guix) repl) "enter-store-monad -- cgit v1.2.3 From fa65e645e93aae288d5122e811a1f4cd02ba64d5 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Sun, 17 Jul 2022 16:22:18 +0200 Subject: doc: Tweak. * doc/guix.texi (Using Guix Interactively): Add @cindex commands. Add missing word. --- doc/guix.texi | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'doc') diff --git a/doc/guix.texi b/doc/guix.texi index 8fc8f53d0e..b47a0c17e8 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -11844,6 +11844,8 @@ configuration file is loaded when spawning a @code{guile} REPL. @node Using Guix Interactively @section Using Guix Interactively +@cindex interactive use +@cindex REPL, read-eval-print loop The @command{guix repl} command gives you access to a warm and friendly @dfn{read-eval-print loop} (REPL) (@pxref{Invoking guix repl}). If you're getting into Guix programming---defining your own packages, @@ -11861,7 +11863,7 @@ guix install guile guile-readline guile-colorized @end example @noindent -... and then create a @file{.guile} in your home directory containing +... and then create a @file{.guile} file in your home directory containing this: @lisp -- cgit v1.2.3 From 969e86784bdba4737baf07d12c5c3117b7c56b48 Mon Sep 17 00:00:00 2001 From: Rostislav Svoboda Date: Tue, 5 Jul 2022 18:35:44 +0200 Subject: doc: Fix the example of "Run `make` automatically" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * doc/contributing.texi (Running Guix Before It Is Installed): add missing command separator '--'. Signed-off-by: Ludovic Courtès --- doc/contributing.texi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'doc') diff --git a/doc/contributing.texi b/doc/contributing.texi index ad312ddeb6..02c7c5ae59 100644 --- a/doc/contributing.texi +++ b/doc/contributing.texi @@ -278,8 +278,8 @@ prepared Guile object (@file{.go}) files. You can run @command{make} automatically as you work using @command{watchexec} from the @code{watchexec} package. For example, -to build again each time you update a package file, you can run -@samp{watchexec -w gnu/packages make -j4}. +to build again each time you update a package file, run +@samp{watchexec -w gnu/packages -- make -j4}. @node The Perfect Setup @section The Perfect Setup -- cgit v1.2.3 From 55725724dd0891e1e195158d0774a3f9a8619361 Mon Sep 17 00:00:00 2001 From: Antero Mejr Date: Tue, 12 Jul 2022 22:50:07 +0000 Subject: home: Add -I, --list-installed option. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * guix/scripts/package.scm (list-installed): New procedure. * guix/scripts/home.scm (%options, show-help): Add '--list-installed'. (process-command): For 'describe' and 'list-generations', honor the 'list-installed option. (display-home-environment-generation): Add #:list-installed-regex and honor it. (list-generations): Likewise. * guix/scripts/utils.scm (pretty-print-table): New argument "left-pad". * doc/guix.texi (Invoking Guix Home): Add information and example for --list-installed flag. Co-authored-by: Ludovic Courtès --- doc/guix.texi | 18 +++++++++++++- guix/scripts/home.scm | 64 ++++++++++++++++++++++++++++++++++-------------- guix/scripts/package.scm | 33 +++++++++++++++---------- guix/utils.scm | 6 ++--- 4 files changed, 85 insertions(+), 36 deletions(-) (limited to 'doc') diff --git a/doc/guix.texi b/doc/guix.texi index b47a0c17e8..c348760dae 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -40495,6 +40495,17 @@ install anything. Describe the current home generation: its file name, as well as provenance information when available. +To show installed packages in the current home generation's profile, the +@code{--list-installed} flag is provided, with the same syntax that is +used in @command{guix package --list-installed} (@pxref{Invoking guix +package}). For instance, the following command shows a table of all the +packages with ``emacs'' in their name that are installed in the current +home generation's profile: + +@example +guix home describe --list-installed=emacs +@end example + @item list-generations List a summary of each generation of the home environment available on disk, in a human-readable way. This is similar to the @@ -40507,9 +40518,14 @@ generations displayed. For instance, the following command displays generations that are up to 10 days old: @example -$ guix home list-generations 10d +guix home list-generations 10d @end example +The @code{--list-installed} flag may also be specified, with the same +syntax that is used in @command{guix home describe}. This may be +helpful if trying to determine when a package was added to the home +profile. + @item import Generate a @dfn{home environment} from the packages in the default profile and configuration files found in the user's home directory. The diff --git a/guix/scripts/home.scm b/guix/scripts/home.scm index 0f5c3388a1..4add7e7c69 100644 --- a/guix/scripts/home.scm +++ b/guix/scripts/home.scm @@ -4,6 +4,7 @@ ;;; Copyright © 2021 Pierre Langlois ;;; Copyright © 2021 Oleg Pykhalov ;;; Copyright © 2022 Ludovic Courtès +;;; Copyright © 2022 Antero Mejr ;;; ;;; This file is part of GNU Guix. ;;; @@ -143,6 +144,11 @@ Some ACTIONS support additional ARGS.\n")) use BACKEND for 'extension-graph' and 'shepherd-graph'")) (newline) (display (G_ " + -I, --list-installed[=REGEXP] + for 'describe' or 'list-generations', list installed + packages matching REGEXP")) + (newline) + (display (G_ " -h, --help display this help and exit")) (display (G_ " -V, --version display version information and exit")) @@ -183,6 +189,9 @@ Some ACTIONS support additional ARGS.\n")) (option '("graph-backend") #t #f (lambda (opt name arg result) (alist-cons 'graph-backend arg result))) + (option '(#\I "list-installed") #f #t + (lambda (opt name arg result) + (alist-cons 'list-installed (or arg "") result))) ;; Container options. (option '(#\N "network") #f #f @@ -569,17 +578,20 @@ Run @command{guix home reconfigure ~a/home-configuration.scm} to effectively deploy the home environment described by these files.\n") destination)))) ((describe) - (match (generation-number %guix-home) - (0 - (leave (G_ "no home environment generation, nothing to describe~%"))) - (generation - (display-home-environment-generation generation)))) + (let ((list-installed-regex (assoc-ref opts 'list-installed))) + (match (generation-number %guix-home) + (0 + (leave (G_ "no home environment generation, nothing to describe~%"))) + (generation + (display-home-environment-generation + generation #:list-installed-regex list-installed-regex))))) ((list-generations) - (let ((pattern (match args + (let ((list-installed-regex (assoc-ref opts 'list-installed)) + (pattern (match args (() #f) ((pattern) pattern) (x (leave (G_ "wrong number of arguments~%")))))) - (list-generations pattern))) + (list-generations pattern #:list-installed-regex list-installed-regex))) ((switch-generation) (let ((pattern (match args ((pattern) pattern) @@ -748,9 +760,11 @@ description matches REGEXPS sorted by relevance, and their score." (define* (display-home-environment-generation number - #:optional (profile %guix-home)) - "Display a summary of home-environment generation NUMBER in a -human-readable format." + #:optional (profile %guix-home) + #:key (list-installed-regex #f)) + "Display a summary of home-environment generation NUMBER in a human-readable +format. List packages in that home environment that match +LIST-INSTALLED-REGEX." (define (display-channel channel) (format #t " ~a:~%" (channel-name channel)) (format #t (G_ " repository URL: ~a~%") (channel-url channel)) @@ -782,24 +796,36 @@ human-readable format." (format #t (G_ " configuration file: ~a~%") (if (supports-hyperlinks?) (file-hyperlink config-file) - config-file)))))) - -(define* (list-generations pattern #:optional (profile %guix-home)) - "Display in a human-readable format all the home environment -generations matching PATTERN, a string. When PATTERN is #f, display -all the home environment generations." + config-file))) + (when list-installed-regex + (format #t (G_ " packages:\n")) + (pretty-print-table (list-installed + list-installed-regex + (list (string-append generation "/profile"))) + #:left-pad 4))))) + +(define* (list-generations pattern #:optional (profile %guix-home) + #:key (list-installed-regex #f)) + "Display in a human-readable format all the home environment generations +matching PATTERN, a string. When PATTERN is #f, display all the home +environment generations. List installed packages that match +LIST-INSTALLED-REGEX." (cond ((not (file-exists? profile)) ; XXX: race condition (raise (condition (&profile-not-found-error (profile profile))))) ((not pattern) - (for-each display-home-environment-generation (profile-generations profile))) + (for-each (cut display-home-environment-generation <> + #:list-installed-regex list-installed-regex) + (profile-generations profile))) ((matching-generations pattern profile) => (lambda (numbers) (if (null-list? numbers) (exit 1) - (leave-on-EPIPE - (for-each display-home-environment-generation numbers))))))) + (leave-on-EPIPE (for-each + (cut display-home-environment-generation <> + #:list-installed-regex list-installed-regex) + numbers))))))) ;;; diff --git a/guix/scripts/package.scm b/guix/scripts/package.scm index 99a6cfaa29..7d92598efa 100644 --- a/guix/scripts/package.scm +++ b/guix/scripts/package.scm @@ -11,6 +11,7 @@ ;;; Copyright © 2020 Simon Tournier ;;; Copyright © 2018 Steve Sprang ;;; Copyright © 2022 Josselin Poiret +;;; Copyright © 2022 Antero Mejr ;;; ;;; This file is part of GNU Guix. ;;; @@ -67,6 +68,7 @@ delete-generations delete-matching-generations guix-package + list-installed search-path-environment-variables manifest-entry-version-prefix @@ -773,6 +775,22 @@ doesn't need it." (add-indirect-root store absolute)) +(define (list-installed regexp profiles) + "Write to the current output port the list of packages matching REGEXP in +PROFILES." + (let* ((regexp (and regexp (make-regexp* regexp regexp/icase))) + (manifest (concatenate-manifests + (map profile-manifest profiles))) + (installed (manifest-entries manifest))) + (leave-on-EPIPE + (let ((rows (filter-map + (match-lambda + (($ name version output path _) + (and (regexp-exec regexp name) + (list name (or version "?") output path)))) + installed))) + rows)))) + ;;; ;;; Queries and actions. @@ -824,19 +842,8 @@ processed, #f otherwise." #t) (('list-installed regexp) - (let* ((regexp (and regexp (make-regexp* regexp regexp/icase))) - (manifest (concatenate-manifests - (map profile-manifest profiles))) - (installed (manifest-entries manifest))) - (leave-on-EPIPE - (let ((rows (filter-map - (match-lambda - (($ name version output path _) - (and (regexp-exec regexp name) - (list name (or version "?") output path)))) - installed))) - ;; Show most recently installed packages last. - (pretty-print-table (reverse rows))))) + ;; Show most recently installed packages last. + (pretty-print-table (reverse (list-installed regexp profiles))) #t) (('list-available regexp) diff --git a/guix/utils.scm b/guix/utils.scm index 745da98a79..329ef62dde 100644 --- a/guix/utils.scm +++ b/guix/utils.scm @@ -1124,11 +1124,11 @@ according to THRESHOLD, then #f is returned." ;;; Prettified output. ;;; -(define* (pretty-print-table rows #:key (max-column-width 20)) +(define* (pretty-print-table rows #:key (max-column-width 20) (left-pad 0)) "Print ROWS in neat columns. All rows should be lists of strings and each row should have the same length. The columns are separated by a tab character, and aligned using spaces. The maximum width of each column is -bound by MAX-COLUMN-WIDTH." +bound by MAX-COLUMN-WIDTH. Each row is prefixed with LEFT-PAD spaces." (let* ((number-of-columns-to-pad (if (null? rows) 0 (1- (length (first rows))))) @@ -1143,7 +1143,7 @@ bound by MAX-COLUMN-WIDTH." (map (cut min <> max-column-width) column-widths))) (fmt (string-append (string-join column-formats "\t") "\t~a"))) - (for-each (cut format #t "~?~%" fmt <>) rows))) + (for-each (cut format #t "~v_~?~%" left-pad fmt <>) rows))) ;;; Local Variables: ;;; eval: (put 'call-with-progress-reporter 'scheme-indent-function 1) -- cgit v1.2.3 From 95acd67dd3d4f1667b97561099ea66f36ee6485e Mon Sep 17 00:00:00 2001 From: Antero Mejr Date: Wed, 13 Jul 2022 15:01:22 +0000 Subject: system: Add -I, --list-installed option. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * guix/scripts/system.scm (display-system-generation): Add #:list-installed-regex and honor it. (list-generations): Likewise. (show-help, %options): Add "--list-installed". (process-command): For 'describe' and 'list-generation', honor the 'list-installed option. * doc/guix.texi (Invoking Guix System): Add information for --list-installed flag. Signed-off-by: Ludovic Courtès --- doc/guix.texi | 12 +++++++++ guix/scripts/system.scm | 67 ++++++++++++++++++++++++++++++++++--------------- 2 files changed, 59 insertions(+), 20 deletions(-) (limited to 'doc') diff --git a/doc/guix.texi b/doc/guix.texi index c348760dae..d8a3d2e90c 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -37781,6 +37781,13 @@ bootloader boot menu: Describe the running system generation: its file name, the kernel and bootloader used, etc., as well as provenance information when available. +The @code{--list-installed} flag is available, with the same +syntax that is used in @command{guix package --list-installed} +(@pxref{Invoking guix package}). When the flag is used, +the description will include a list of packages that are currently +installed in the system profile, with optional filtering based on a +regular expression. + @quotation Note The @emph{running} system generation---referred to by @file{/run/current-system}---is not necessarily the @emph{current} @@ -37808,6 +37815,11 @@ generations that are up to 10 days old: $ guix system list-generations 10d @end example +The @code{--list-installed} flag may also be specified, with the same +syntax that is used in @command{guix package --list-installed}. This +may be helpful if trying to determine when a package was added to the +system. + @end table The @command{guix system} command has even more to offer! The following diff --git a/guix/scripts/system.scm b/guix/scripts/system.scm index b9084a401c..bfde0a88ca 100644 --- a/guix/scripts/system.scm +++ b/guix/scripts/system.scm @@ -50,7 +50,8 @@ #:use-module (guix channels) #:use-module (guix scripts build) #:autoload (guix scripts package) (delete-generations - delete-matching-generations) + delete-matching-generations + list-installed) #:autoload (guix scripts pull) (channel-commit-hyperlink) #:autoload (guix graph) (export-graph node-type graph-backend-name lookup-backend) @@ -480,8 +481,10 @@ list of services." ;;; (define* (display-system-generation number - #:optional (profile %system-profile)) - "Display a summary of system generation NUMBER in a human-readable format." + #:optional (profile %system-profile) + #:key (list-installed-regex #f)) + "Display a summary of system generation NUMBER in a human-readable format. +List packages in that system that match LIST-INSTALLED-REGEX." (define (display-channel channel) (format #t " ~a:~%" (channel-name channel)) (format #t (G_ " repository URL: ~a~%") (channel-url channel)) @@ -544,23 +547,35 @@ list of services." (format #t (G_ " configuration file: ~a~%") (if (supports-hyperlinks?) (file-hyperlink config-file) - config-file)))))) - -(define* (list-generations pattern #:optional (profile %system-profile)) + config-file))) + (when list-installed-regex + (format #t (G_ " packages:\n")) + (pretty-print-table (list-installed + list-installed-regex + (list (string-append generation "/profile"))) + #:left-pad 4))))) + +(define* (list-generations pattern #:optional (profile %system-profile) + #:key (list-installed-regex #f)) "Display in a human-readable format all the system generations matching -PATTERN, a string. When PATTERN is #f, display all the system generations." +PATTERN, a string. When PATTERN is #f, display all the system generations. +List installed packages that match LIST-INSTALLED-REGEX." (cond ((not (file-exists? profile)) ; XXX: race condition (raise (condition (&profile-not-found-error (profile profile))))) ((not pattern) - (for-each display-system-generation (profile-generations profile))) + (for-each (cut display-system-generation <> + #:list-installed-regex list-installed-regex) + (profile-generations profile))) ((matching-generations pattern profile) => (lambda (numbers) (if (null-list? numbers) (exit 1) (leave-on-EPIPE - (for-each display-system-generation numbers))))))) + (for-each (cut display-system-generation <> + #:list-installed-regex list-installed-regex) + numbers))))))) ;;; @@ -1032,6 +1047,11 @@ Some ACTIONS support additional ARGS.\n")) use BACKEND for 'extension-graphs' and 'shepherd-graph'")) (newline) (display (G_ " + -I, --list-installed[=REGEXP] + for 'describe' and 'list-generations', list installed + packages matching REGEXP")) + (newline) + (display (G_ " -h, --help display this help and exit")) (display (G_ " -V, --version display version information and exit")) @@ -1135,6 +1155,9 @@ Some ACTIONS support additional ARGS.\n")) (option '("graph-backend") #t #f (lambda (opt name arg result) (alist-cons 'graph-backend arg result))) + (option '(#\I "list-installed") #f #t + (lambda (opt name arg result) + (alist-cons 'list-installed (or arg "") result))) %standard-build-options)) (define %default-options @@ -1322,25 +1345,29 @@ argument list and OPTS is the option alist." ;; The following commands do not need to use the store, and they do not need ;; an operating system configuration file. ((list-generations) - (let ((pattern (match args + (let ((list-installed-regex (assoc-ref opts 'list-installed)) + (pattern (match args (() #f) ((pattern) pattern) (x (leave (G_ "wrong number of arguments~%")))))) - (list-generations pattern))) + (list-generations pattern #:list-installed-regex list-installed-regex))) ((describe) ;; Describe the running system, which is not necessarily the current ;; generation. /run/current-system might point to ;; /var/guix/profiles/system-N-link, or it might point directly to ;; /gnu/store/…-system. Try both. - (match (generation-number "/run/current-system" %system-profile) - (0 - (match (generation-number %system-profile) - (0 - (leave (G_ "no system generation, nothing to describe~%"))) - (generation - (display-system-generation generation)))) - (generation - (display-system-generation generation)))) + (let ((list-installed-regex (assoc-ref opts 'list-installed))) + (match (generation-number "/run/current-system" %system-profile) + (0 + (match (generation-number %system-profile) + (0 + (leave (G_ "no system generation, nothing to describe~%"))) + (generation + (display-system-generation + generation #:list-installed-regex list-installed-regex)))) + (generation + (display-system-generation + generation #:list-installed-regex list-installed-regex))))) ((search) (apply (resolve-subcommand "search") args)) ((edit) -- cgit v1.2.3 From be7b314f3fe22273e935accac22f313e44d3d970 Mon Sep 17 00:00:00 2001 From: Ricardo Wurmus Date: Tue, 19 Jul 2022 23:44:11 +0200 Subject: import: Enable recursive import for texlive packages. * guix/import/texlive.scm (tlpdb->package): Add VERSION argument; include explicit version field in output. (texlive->guix-package): Set default value for VERSION argument; adjust call of tlpdb->package. (texlive-recursive-import): Accept REPO and VERSION keyword arguments. * guix/import/utils.scm (package->definition): Add a clause to deal with output from tlpdb->package. * guix/scripts/import/texlive.scm (%options): Add "recursive" option. (guix-import-texlive): Honor "recursive" option. * doc/guix.texi (Using TeX and LaTeX): Mention "recursive" option. --- doc/guix.texi | 10 ++++++++++ guix/import/texlive.scm | 20 +++++++++++++++----- guix/import/utils.scm | 2 ++ guix/scripts/import/texlive.scm | 25 +++++++++++++++++++------ 4 files changed, 46 insertions(+), 11 deletions(-) (limited to 'doc') diff --git a/doc/guix.texi b/doc/guix.texi index d8a3d2e90c..3c5864ec1a 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -40965,6 +40965,16 @@ package, you can try and import it (@pxref{Invoking guix import}): guix import texlive @var{package} @end example +Additional options include: + +@table @code +@item --recursive +@itemx -r +Traverse the dependency graph of the given upstream package recursively +and generate package expressions for all those packages that are not yet +in Guix. +@end table + @quotation Note @TeX{} Live packaging is still very much work in progress, but you can help! @xref{Contributing}, for more information. diff --git a/guix/import/texlive.scm b/guix/import/texlive.scm index c741555928..116bd1f66a 100644 --- a/guix/import/texlive.scm +++ b/guix/import/texlive.scm @@ -246,7 +246,7 @@ of those files are returned that are unexpectedly installed." ;; entries with the same prefix. (lambda (x y) (every equal? x y))))) -(define (tlpdb->package name package-database) +(define (tlpdb->package name version package-database) (and-let* ((data (assoc-ref package-database name)) (dirs (files->directories (map (lambda (dir) @@ -255,7 +255,9 @@ of those files are returned that are unexpectedly installed." (or (assoc-ref data 'runfiles) (list)) (or (assoc-ref data 'srcfiles) (list)))))) (name (guix-name name)) - (version (number->string %texlive-revision)) + ;; TODO: we're ignoring the VERSION argument because that + ;; information is distributed across %texlive-tag and + ;; %texlive-revision. (ref (svn-multi-reference (url (string-append "svn://www.tug.org/texlive/tags/" %texlive-tag "/Master/texmf-dist")) @@ -276,6 +278,9 @@ of those files are returned that are unexpectedly installed." (force-output port) (get-hash)))) ,@(if (assoc-ref data 'srcfiles) '() '(#:trivial? #true)))) + ;; package->definition in (guix import utils) expects to see a + ;; version field. + (version ,version) ,@(or (and=> (assoc-ref data 'depend) (lambda (inputs) `((propagated-inputs @@ -297,13 +302,18 @@ of those files are returned that are unexpectedly installed." (define texlive->guix-package (memoize - (lambda* (name #:key repo version (package-database tlpdb)) + (lambda* (name #:key + repo + (version (number->string %texlive-revision)) + (package-database tlpdb)) "Find the metadata for NAME in the tlpdb and return the `package' s-expression corresponding to that package, or #f on failure." - (tlpdb->package name (package-database))))) + (tlpdb->package name version (package-database))))) -(define (texlive-recursive-import name) +(define* (texlive-recursive-import name #:key repo version) (recursive-import name + #:repo repo + #:version version #:repo->guix-package texlive->guix-package #:guix-name guix-name)) diff --git a/guix/import/utils.scm b/guix/import/utils.scm index 26eebfece5..668b8c8083 100644 --- a/guix/import/utils.scm +++ b/guix/import/utils.scm @@ -341,6 +341,8 @@ APPEND-VERSION?/string is a string, append this string." (match guix-package ((or ('package ('name name) ('version version) . rest) + ('package ('inherit ('simple-texlive-package name . _)) + ('version version) . rest) ('let _ ('package ('name name) ('version version) . rest))) `(define-public ,(string->symbol diff --git a/guix/scripts/import/texlive.scm b/guix/scripts/import/texlive.scm index c5dcc07ea1..203386e31c 100644 --- a/guix/scripts/import/texlive.scm +++ b/guix/scripts/import/texlive.scm @@ -22,11 +22,13 @@ #:use-module (guix utils) #:use-module (guix scripts) #:use-module (guix import texlive) + #:use-module (guix import utils) #:use-module (guix scripts import) #:use-module (srfi srfi-1) #:use-module (srfi srfi-11) #:use-module (srfi srfi-37) #:use-module (srfi srfi-41) + #:use-module (srfi srfi-71) #:use-module (ice-9 match) #:use-module (ice-9 format) #:export (guix-import-texlive)) @@ -58,6 +60,9 @@ Import and convert the Texlive package for PACKAGE-NAME.\n")) (option '(#\V "version") #f #f (lambda args (show-version-and-exit "guix import texlive"))) + (option '(#\r "recursive") #f #f + (lambda (opt name arg result) + (alist-cons 'recursive #t result))) %standard-import-options)) @@ -78,12 +83,20 @@ Import and convert the Texlive package for PACKAGE-NAME.\n")) (_ #f)) (reverse opts)))) (match args - ((name) - (let ((sexp (texlive->guix-package name))) - (unless sexp - (leave (G_ "failed to import package '~a'~%") - name)) - sexp)) + ((spec) + (let ((name version (package-name->name+version spec))) + (if (assoc-ref opts 'recursive) + ;; Recursive import + (with-error-handling + (map package->definition + (filter identity (texlive-recursive-import name + #:version version)))) + ;; Single import + (let ((sexp (texlive->guix-package name #:version version))) + (unless sexp + (leave (G_ "failed to download description for package '~a'~%") + name)) + sexp)))) (() (leave (G_ "too few arguments~%"))) ((many ...) -- cgit v1.2.3