raco: show all the matching commands for an ambiguous prefix

This commit is contained in:
Gustavo Massaccesi 2016-09-24 17:04:12 -03:00 committed by Matthew Flatt
parent 056041bd07
commit 409321c03b

View File

@ -1,27 +1,38 @@
#lang racket/base #lang racket/base
(require "command-name.rkt" (require "command-name.rkt"
"all-tools.rkt") "all-tools.rkt"
racket/string)
(module test racket/base) (module test racket/base)
(define (find-by-prefix hash str) (define (filter-by-prefix hash str)
(let ([trie (make-hash)]) (for/hash ([key (in-hash-keys hash)]
(for ([key (in-hash-keys hash)]) #:when (string-prefix? key str))
(for/fold ([trie trie]) ([c (string->list key)]) (values key (hash-ref hash key))))
(let ([next (hash-ref trie c (lambda () (make-hash)))])
(if (hash-ref next #f #f) (define (filter-importance hash)
(hash-set! next #f null) (for/hash ([key (in-hash-keys hash)]
(hash-set! next #f key)) #:when (cadddr (hash-ref hash key)))
(hash-set! trie c next) (values key (hash-ref hash key))))
next)))
(let ([t (for/fold ([trie trie]) ([c (string->list str)]) ; sort methods for show-tools
(and trie (define (alphabetic<? a b)
(hash-ref trie c #f)))]) (string<? (car a) (car b)))
(and t
(let ([s (hash-ref t #f #f)]) (define (importance<? a b)
(if (string? s) (> (or (cadddr a) -inf.0)
(hash-ref hash s) (or (cadddr b) -inf.0)))
'ambiguous))))))
(define (show-tools msg tools all-tools <?)
(eprintf "\n~a commands:\n" msg)
(define l (sort (hash-map tools (lambda (k v) v)) <?))
(define largest (apply max 0 (hash-map all-tools
(lambda (k v) (string-length (car v))))))
(for ([i (in-list l)])
(eprintf " ~a~a~a\n"
(car i)
(make-string (- largest -3 (string-length (car i))) #\space)
(caddr i))))
(define (done [result 0]) (define (done [result 0])
((executable-yield-handler) result) ; to enable GUI commands ((executable-yield-handler) result) ; to enable GUI commands
@ -35,6 +46,14 @@
(list* (cadr cmdline) "--help" (cddr cmdline)) (list* (cadr cmdline) "--help" (cddr cmdline))
cmdline)] cmdline)]
[tools (all-tools)] [tools (all-tools)]
[prefix-tools (if (pair? cmdline)
(filter-by-prefix tools (car cmdline))
#hasheq())]
[tool (and (pair? cmdline)
(or (hash-ref tools (car cmdline) #f)
(and (= (hash-count prefix-tools) 1)
(hash-ref tools (car cmdline) #f))))]
[ambiguous? (> (hash-count prefix-tools) 1)]
[show-all? [show-all?
(cond (cond
[(null? cmdline) #f] [(null? cmdline) #f]
@ -46,20 +65,16 @@
(find-system-path 'run-file) (find-system-path 'run-file)
(car cmdline)) (car cmdline))
#f] #f]
[(or (hash-ref tools (car cmdline) #f) [tool
(find-by-prefix tools (car cmdline))) (parameterize ([current-command-line-arguments (list->vector (cdr cmdline))]
=> (lambda (tool) [current-command-name (car tool)])
(if (eq? 'ambiguous tool) (dynamic-require (cadr tool) #f)
(begin (done))]
[ambiguous?
(eprintf "~a: Ambiguous command prefix: ~a\n\n" (eprintf "~a: Ambiguous command prefix: ~a\n\n"
(find-system-path 'run-file) (find-system-path 'run-file)
(car cmdline)) (car cmdline))
#f) #f]
(parameterize ([current-command-line-arguments
(list->vector (cdr cmdline))]
[current-command-name (car tool)])
(dynamic-require (cadr tool) #f)
(done))))]
[(equal? (car cmdline) "help") #t] [(equal? (car cmdline) "help") #t]
[else [else
(eprintf "~a: Unrecognized command: ~a\n\n" (eprintf "~a: Unrecognized command: ~a\n\n"
@ -67,24 +82,11 @@
(car cmdline)) (car cmdline))
#f])]) #f])])
(eprintf "Usage: raco <command> <option> ... <arg> ...\n") (eprintf "Usage: raco <command> <option> ... <arg> ...\n")
(for-each (when ambiguous?
(lambda (show-all?) (show-tools "Matching" prefix-tools tools importance<?))
(eprintf "\n~a commands:\n" (show-tools "Frequently used" (filter-importance tools) tools importance<?)
(if show-all? "All available" "Frequently used")) (when show-all?
(let ([l (sort (hash-map tools (lambda (k v) v)) (show-tools "All available" tools tools alphabetic<?))
(if show-all?
(lambda (a b) (string<? (car a) (car b)))
(lambda (a b) (> (or (list-ref a 3) -inf.0) (or (list-ref b 3) -inf.0)))))])
(let ([largest (apply max 0 (map (lambda (v) (string-length (car v))) l))])
(for ([i (in-list l)])
(when (or show-all? (cadddr i))
(eprintf " ~a~a~a\n"
(car i)
(make-string (- largest -3 (string-length (car i))) #\space)
(caddr i)))))))
(if show-all?
(list #f #t)
(list #f)))
(printf "\nA command can be specified by an unambiguous prefix.") (printf "\nA command can be specified by an unambiguous prefix.")
(unless show-all? (unless show-all?
(printf "\nSee `raco help' for a complete list of commands.")) (printf "\nSee `raco help' for a complete list of commands."))