;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; CLI for sr.ht ;;; ;;; Copyright (c) 2019, Evan Hanson ;;; ;;; See LICENSE for details. ;;; (declare (module (topham cli))) (import (chicken condition) (chicken keyword) (chicken io) (chicken pretty-print) (chicken process-context) (chicken string) (topham) (topham builds) (medea) (optimism getopt-long) (simple-exceptions) (srfi 1)) (import-syntax (matchable)) (define common-options '((--access-token . token) ((-o --output) . format) ((-h --help)))) (define output-format (make-parameter "s" string->symbol)) (define (alist-ref* keys . args) (any (lambda (key) (apply alist-ref key args)) keys)) (define (error-message e) (let ((m (message e)) (a (arguments e))) (if (null? a) m (conc m ": " (string-intersperse (map conc a) ", "))))) (define (print-json . args) (apply write-json args) (print)) (define (string->id x) (let ((id (string->number x))) (if (and (integer? id) (positive? id)) id (error "Invalid ID" x)))) (define (crud? x) (and (pair? x) (pair? (car x)) (keyword? (caar x)))) (define (output x) (let ((printer (case (output-format) ((s) pretty-print) ((j json) print-json)))) (cond ((crud? x) (printer (cdr x))) ((string? x) (print (string-chomp x))) (else (printer x))))) (define (create-job args) (define opts (parse-command-line args '(((-m --manifest) . input) ((-n --note) . message)))) (define note (alist-ref* '(-n --note) opts)) (define manifest (let ((x (alist-ref* '(-m --manifest) opts eq? "-"))) (if (equal? x "-") (read-string) (with-input-from-file x read-string)))) (define details (append (list manifest: manifest) (if (not note) (list) (list note: note)))) (match (assq '-- opts) ((_) (output (create (apply job details)))) ((_ . _) (usage (current-error-port)) (exit 1)))) (define (get-manifest id) (output (retrieve (manifest (string->id id))))) (define (get-job id) (output (retrieve (job (string->id id))))) (define (usage #!optional (port (current-output-port))) (parameterize ((current-output-port port)) (print "Usage: " (program-name) " [options ...] command ...") (print) (print "Commands:") (print " get job Fetch job details") (print " get manifest Fetch job manifest") (print " create job Create job") (print " -m, --manifest manifest (stdin)") (print " -n, --note description") (print) (print "Options:") (print " --access-token Set API token (SRHT_ACCESS_TOKEN)") (print " -o, --output Set output format {s|j|json} (s)") (print " -h, --help Show this message") (print))) (define (handle-global-options! opts) (and-let* ((help (alist-ref* '(-h --help) opts))) (usage) (exit 0)) (and-let* ((format (alist-ref* '(-o --output) opts))) (output-format format) (unless (member (output-format) '(s j json)) (error "Invalid output format" format))) (and-let* ((token (alist-ref '--access-token opts))) (access-token token))) (define (main args) (let ((opts (parse-command-line args common-options))) (handle-global-options! opts) (match (assq '-- opts) ((_ "get" "job" id) (get-job id)) ((_ "create" "job" . args*) (create-job args*)) ((_ "get" "manifest" id) (get-manifest id)) ((_ . _) (usage (current-error-port)) (exit 1))))) (cond-expand (compiling (with-exception-handler (lambda (e) (pp (condition->list e)) (print "Error: " (error-message e)) (exit 1)) (lambda () (main (command-line-arguments))))) (else))