From db5a94445f3b21b307c73ea72ed495bda891ef28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= Date: Mon, 4 Jan 2016 22:27:38 +0100 Subject: [PATCH] guix package: Allow multiple '--search' flags. * guix/scripts/package.scm (find-packages-by-description): Change 'rx' parameter to 'regexps'. [matches-all?, matches-one?]: New procedures. Use them. (process-query): Collect regexps from all 'search' queries, and pass them to 'find-packages-by-description'. * tests/guix-package.sh: Add tests. * doc/guix.texi (Invoking guix package): Document it. --- doc/guix.texi | 17 ++++++++++++++++- guix/scripts/package.scm | 33 ++++++++++++++++++++------------- tests/guix-package.sh | 20 +++++++++++++++++--- 3 files changed, 53 insertions(+), 17 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index f155fbe818..a07bf824d6 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -10,7 +10,7 @@ @include version.texi @copying -Copyright @copyright{} 2012, 2013, 2014, 2015 Ludovic Courtès@* +Copyright @copyright{} 2012, 2013, 2014, 2015, 2016 Ludovic Courtès@* Copyright @copyright{} 2013, 2014 Andreas Enge@* Copyright @copyright{} 2013 Nikita Karetnikov@* Copyright @copyright{} 2015 Mathieu Lirzin@* @@ -1462,6 +1462,21 @@ name: gmp @dots{} @end example +It is also possible to refine search results using several @code{-s} +flags. For example, the following command returns a list of board +games: + +@example +$ guix package -s '\' -s game | recsel -p name +name: gnubg +@dots{} +@end example + +If we were to omit @code{-s game}, we would also get software packages +that deal with printed circuit boards; removing the angle brackets +around @code{board} would further add packages that have to do with +keyboards. + @item --show=@var{package} Show details about @var{package}, taken from the list of available packages, in @code{recutils} format (@pxref{Top, GNU recutils databases,, recutils, GNU diff --git a/guix/scripts/package.scm b/guix/scripts/package.scm index d0b5abd0e2..02eb600c43 100644 --- a/guix/scripts/package.scm +++ b/guix/scripts/package.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012, 2013, 2014, 2015 Ludovic Courtès +;;; Copyright © 2012, 2013, 2014, 2015, 2016 Ludovic Courtès ;;; Copyright © 2013 Nikita Karetnikov ;;; Copyright © 2013, 2015 Mark H Weaver ;;; Copyright © 2014 Alex Kost @@ -230,21 +230,24 @@ specified in MANIFEST, a manifest object." ;;; Package specifications. ;;; -(define (find-packages-by-description rx) - "Return the list of packages whose name, synopsis, or description matches -RX." +(define (find-packages-by-description regexps) + "Return the list of packages whose name matches one of REGEXPS, or whose +synopsis or description matches all of REGEXPS." (define version=?)) + (define (matches-all? str) + (every (cut regexp-exec <> str) regexps)) + + (define (matches-one? str) + (find (cut regexp-exec <> str) regexps)) + (sort (fold-packages (lambda (package result) - (define matches? - (cut regexp-exec rx <>)) - - (if (or (matches? (package-name package)) + (if (or (matches-one? (package-name package)) (and=> (package-synopsis package) - (compose matches? P_)) + (compose matches-all? P_)) (and=> (package-description package) - (compose matches? P_))) + (compose matches-all? P_))) (cons package result) result)) '()) @@ -696,11 +699,15 @@ processed, #f otherwise." (package-name p2)))))) #t)) - (('search regexp) - (let ((regexp (make-regexp* regexp regexp/icase))) + (('search _) + (let* ((patterns (filter-map (match-lambda + (('query 'search rx) rx) + (_ #f)) + opts)) + (regexps (map (cut make-regexp* <> regexp/icase) patterns))) (leave-on-EPIPE (for-each (cute package->recutils <> (current-output-port)) - (find-packages-by-description regexp))) + (find-packages-by-description regexps))) #t)) (('show requested-name) diff --git a/tests/guix-package.sh b/tests/guix-package.sh index 5e6ff8b012..cf1a185590 100644 --- a/tests/guix-package.sh +++ b/tests/guix-package.sh @@ -1,5 +1,5 @@ # GNU Guix --- Functional package management for GNU -# Copyright © 2012, 2013, 2014, 2015 Ludovic Courtès +# Copyright © 2012, 2013, 2014, 2015, 2016 Ludovic Courtès # Copyright © 2013 Nikita Karetnikov # # This file is part of GNU Guix. @@ -30,9 +30,10 @@ readlink_base () module_dir="t-guix-package-$$" profile="t-profile-$$" -rm -f "$profile" +tmpfile="t-guix-package-file-$$" +rm -f "$profile" "$tmpfile" -trap 'rm -f "$profile" "$profile-"[0-9]* ; rm -rf "$module_dir" t-home-'"$$" EXIT +trap 'rm -f "$profile" "$profile-"[0-9]* "$tmpfile"; rm -rf "$module_dir" t-home-'"$$" EXIT # Use `-e' with a non-package expression. if guix package --bootstrap -e +; @@ -96,6 +97,19 @@ test "`guix package -s "An example GNU package" | grep ^name:`" = \ "name: hello" test -z "`guix package -s "n0t4r341p4ck4g3"`" +# Search with one and then two regexps. +# First we get printed circuit boards *and* board games. +guix package -s '\' > "$tmpfile" +grep '^name: pcb' "$tmpfile" +grep '^name: gnubg' "$tmpfile" + +# Second we get only board games. +guix package -s '\' -s game > "$tmpfile" +grep -v '^name: pcb' "$tmpfile" > /dev/null +grep '^name: gnubg' "$tmpfile" + +rm -f "$tmpfile" + # Make sure `--search' can display all the packages. guix package --search="" > /dev/null