;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; main.rkt ;; Richard Cobbe ;; January 2011 ;; ;; Main interface for functional command line library. Defines the ;; command-line macro that is the primary entry point. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; #lang racket (require "parser.rkt" "match.rkt") (provide functional-command-line (struct-out exn:functional-command:parse)) ;; XXX we call this functional-command-line to avoid a conflict with ;; command-line. Is there a way to resolve conflicts w/ e.g. module prefixes ;; in a Scribble manual? ;; functional-command-line :: SExpr (U (Listof String) (Vectorof String)) ;; -> Anything ;; raises exn:functional-command:parse ;; on match failure, prints relevant usage & terminates (define functional-command-line (lambda (spec args) (with-handlers ([exn:fc:help-request? (print-exn (current-output-port) (current-output-port))] [exn:fc:match? (print-exn (current-error-port) (current-output-port))]) (functional-command-line* spec args)))) ;; functional-command-line* :: SExpr (U (Listof String) (Vectorof String)) ;; -> Anything ;; raises exn:functional-command:match, exn:functional-command:parse (define functional-command-line* (lambda (spec args) (let ([args (if (vector? args) (vector->list args) args)]) (match-spec (parse-spec spec) args)))) ;; print-exn :: Output-Port Output-Port -> Exn:FC:Match -> a ;; prints e's message to error-port (unless empty), prints e's usage info to ;; usage-port, and exits. (define print-exn (lambda (error-port usage-port) (lambda (e) (let ([msg (exn-message e)]) (unless (string=? msg "") (fprintf error-port msg)) (fprintf usage-port (exn:fc:match-usage-info e)) (exit 1))))) ;; XXX thought about simple macro interface with lousy error checking, but I'll ;; have to think very carefully about the right way to do error checking here. ;; - how to verify that, e.g., the first element of a spec is a string, while ;; still allowing it to be an arbitrary expression?