ui: Generalize relevance computation.

* guix/ui.scm (relevance, package-relevance): New procedures.
(%package-metrics): New variable.
* guix/scripts/package.scm (find-packages-by-description)[score]
[package-score]: Remove.  Use 'package-relevance' instead.
This commit is contained in:
Ludovic Courtès 2017-09-13 15:07:17 +02:00
parent dab666cd8d
commit c7ae219e39
No known key found for this signature in database
GPG Key ID: 090B11993D9AEBB5
2 changed files with 44 additions and 20 deletions

@ -246,27 +246,8 @@ specified in MANIFEST, a manifest object."
"Return two values: the list of packages whose name, synopsis, or
description matches at least one of REGEXPS sorted by relevance, and the list
of relevance scores."
(define (score str)
(let ((counts (filter-map (lambda (regexp)
(match (regexp-exec regexp str)
(#f #f)
(m (match:count m))))
regexps)))
;; Compute a score that's proportional to the number of regexps matched
;; and to the number of matches for each regexp.
(* (length counts) (reduce + 0 counts))))
(define (package-score package)
(+ (* 3 (score (package-name package)))
(* 2 (match (package-synopsis package)
((? string? str) (score (P_ str)))
(#f 0)))
(match (package-description package)
((? string? str) (score (P_ str)))
(#f 0))))
(let ((matches (fold-packages (lambda (package result)
(match (package-score package)
(match (package-relevance package regexps)
((? zero?)
result)
(score

@ -85,6 +85,8 @@
string->recutils
package->recutils
package-specification->name+version+output
relevance
package-relevance
string->generations
string->duration
matching-generations
@ -1024,6 +1026,47 @@ WIDTH columns. EXTRA-FIELDS is a list of symbol/value pairs to emit."
extra-fields)
(newline port))
(define (relevance obj regexps metrics)
"Compute a \"relevance score\" for OBJ as a function of its number of
matches of REGEXPS and accordingly to METRICS. METRICS is list of
field/weight pairs, where FIELD is a procedure that returns a string
describing OBJ, and WEIGHT is a positive integer denoting the weight of this
field in the final score.
A score of zero means that OBJ does not match any of REGEXPS. The higher the
score, the more relevant OBJ is to REGEXPS."
(define (score str)
(let ((counts (filter-map (lambda (regexp)
(match (regexp-exec regexp str)
(#f #f)
(m (match:count m))))
regexps)))
;; Compute a score that's proportional to the number of regexps matched
;; and to the number of matches for each regexp.
(* (length counts) (reduce + 0 counts))))
(fold (lambda (metric relevance)
(match metric
((field . weight)
(match (field obj)
(#f relevance)
(str (+ relevance
(* (score str) weight)))))))
0
metrics))
(define %package-metrics
;; Metrics used to compute the "relevance score" of a package against a set
;; of regexps.
`((,package-name . 3)
(,package-synopsis-string . 2)
(,package-description-string . 1)))
(define (package-relevance package regexps)
"Return a score denoting the relevance of PACKAGE for REGEXPS. A score of
zero means that PACKAGE does not match any of REGEXPS."
(relevance package regexps %package-metrics))
(define (string->generations str)
"Return the list of generations matching a pattern in STR. This function
accepts the following patterns: \"1\", \"1,2,3\", \"1..9\", \"1..\", \"..9\"."