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.
This commit is contained in:
Ludovic Courtès 2016-01-04 22:27:38 +01:00
parent d28ef43937
commit db5a94445f
3 changed files with 53 additions and 17 deletions

View File

@ -10,7 +10,7 @@
@include version.texi @include version.texi
@copying @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, 2014 Andreas Enge@*
Copyright @copyright{} 2013 Nikita Karetnikov@* Copyright @copyright{} 2013 Nikita Karetnikov@*
Copyright @copyright{} 2015 Mathieu Lirzin@* Copyright @copyright{} 2015 Mathieu Lirzin@*
@ -1462,6 +1462,21 @@ name: gmp
@dots{} @dots{}
@end example @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 '\<board\>' -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} @item --show=@var{package}
Show details about @var{package}, taken from the list of available packages, in Show details about @var{package}, taken from the list of available packages, in
@code{recutils} format (@pxref{Top, GNU recutils databases,, recutils, GNU @code{recutils} format (@pxref{Top, GNU recutils databases,, recutils, GNU

View File

@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU ;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2012, 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2012, 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2013 Nikita Karetnikov <nikita@karetnikov.org> ;;; Copyright © 2013 Nikita Karetnikov <nikita@karetnikov.org>
;;; Copyright © 2013, 2015 Mark H Weaver <mhw@netris.org> ;;; Copyright © 2013, 2015 Mark H Weaver <mhw@netris.org>
;;; Copyright © 2014 Alex Kost <alezost@gmail.com> ;;; Copyright © 2014 Alex Kost <alezost@gmail.com>
@ -230,21 +230,24 @@ specified in MANIFEST, a manifest object."
;;; Package specifications. ;;; Package specifications.
;;; ;;;
(define (find-packages-by-description rx) (define (find-packages-by-description regexps)
"Return the list of packages whose name, synopsis, or description matches "Return the list of packages whose name matches one of REGEXPS, or whose
RX." synopsis or description matches all of REGEXPS."
(define version<? (negate version>=?)) (define version<? (negate version>=?))
(define (matches-all? str)
(every (cut regexp-exec <> str) regexps))
(define (matches-one? str)
(find (cut regexp-exec <> str) regexps))
(sort (sort
(fold-packages (lambda (package result) (fold-packages (lambda (package result)
(define matches? (if (or (matches-one? (package-name package))
(cut regexp-exec rx <>))
(if (or (matches? (package-name package))
(and=> (package-synopsis package) (and=> (package-synopsis package)
(compose matches? P_)) (compose matches-all? P_))
(and=> (package-description package) (and=> (package-description package)
(compose matches? P_))) (compose matches-all? P_)))
(cons package result) (cons package result)
result)) result))
'()) '())
@ -696,11 +699,15 @@ processed, #f otherwise."
(package-name p2)))))) (package-name p2))))))
#t)) #t))
(('search regexp) (('search _)
(let ((regexp (make-regexp* regexp regexp/icase))) (let* ((patterns (filter-map (match-lambda
(('query 'search rx) rx)
(_ #f))
opts))
(regexps (map (cut make-regexp* <> regexp/icase) patterns)))
(leave-on-EPIPE (leave-on-EPIPE
(for-each (cute package->recutils <> (current-output-port)) (for-each (cute package->recutils <> (current-output-port))
(find-packages-by-description regexp))) (find-packages-by-description regexps)))
#t)) #t))
(('show requested-name) (('show requested-name)

View File

@ -1,5 +1,5 @@
# GNU Guix --- Functional package management for GNU # GNU Guix --- Functional package management for GNU
# Copyright © 2012, 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org> # Copyright © 2012, 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
# Copyright © 2013 Nikita Karetnikov <nikita@karetnikov.org> # Copyright © 2013 Nikita Karetnikov <nikita@karetnikov.org>
# #
# This file is part of GNU Guix. # This file is part of GNU Guix.
@ -30,9 +30,10 @@ readlink_base ()
module_dir="t-guix-package-$$" module_dir="t-guix-package-$$"
profile="t-profile-$$" 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. # Use `-e' with a non-package expression.
if guix package --bootstrap -e +; if guix package --bootstrap -e +;
@ -96,6 +97,19 @@ test "`guix package -s "An example GNU package" | grep ^name:`" = \
"name: hello" "name: hello"
test -z "`guix package -s "n0t4r341p4ck4g3"`" 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 '\<board\>' > "$tmpfile"
grep '^name: pcb' "$tmpfile"
grep '^name: gnubg' "$tmpfile"
# Second we get only board games.
guix package -s '\<board\>' -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. # Make sure `--search' can display all the packages.
guix package --search="" > /dev/null guix package --search="" > /dev/null