124 lines
3.7 KiB
Common Lisp
124 lines
3.7 KiB
Common Lisp
;;;; timecalc.lisp
|
|
|
|
(defpackage #:timecalc
|
|
(:use #:cl #:with-user-abort)
|
|
(:import-from :timecalc-logic
|
|
:convert
|
|
:reload-models
|
|
:opts-ensure-directory)
|
|
(:import-from :timecalc-web
|
|
:start-server)
|
|
(:import-from :unix-opts
|
|
:get-opts
|
|
:define-opts))
|
|
|
|
(in-package #:timecalc)
|
|
|
|
;; defines all of our command line arguments
|
|
(define-opts
|
|
(:name :help
|
|
:description "prints this help"
|
|
:short #\h
|
|
:long "help")
|
|
(:name :web
|
|
:description "starts the web interface (defaults to 9001)"
|
|
:long "web")
|
|
(:name :port
|
|
:description "port for the web server to run"
|
|
:long "port"
|
|
:arg-parser #'parse-integer
|
|
:meta-var "PORT")
|
|
(:name :from
|
|
:description "specifies what planet's time you want to convert from"
|
|
:short #\f
|
|
:long "from"
|
|
:arg-parser #'identity
|
|
:meta-var "FROM")
|
|
(:name :to
|
|
:description "specifies what planet's time you want to convert to"
|
|
:short #\t
|
|
:long "to"
|
|
:arg-parser #'identity
|
|
:meta-var "TO")
|
|
(:name :version
|
|
:description "prints the version of the app"
|
|
:long "version")
|
|
(:name :load
|
|
:description "loads extra models from DIRECTORY"
|
|
:short #\l
|
|
:long "load"
|
|
:required t
|
|
:arg-parser #'opts-ensure-directory
|
|
:meta-var "DIRECTORY"))
|
|
|
|
(define-condition timecalc-signal ()
|
|
((message :initarg :message :reader message)
|
|
(args :initarg :args :reader signal-args
|
|
:initform nil)))
|
|
|
|
(defun main ()
|
|
"binary entry point"
|
|
|
|
;; ensures that if we only pass --version or --help
|
|
;; we don't worry about the required --load option
|
|
(handler-bind ((opts:missing-required-option
|
|
#'(lambda (x) (invoke-restart 'opts:skip-option))))
|
|
(multiple-value-bind (opts args) (get-opts)
|
|
;; if we get passed --help OR the binary is ran with NO arguments at all
|
|
(when (or (getf opts :help)
|
|
(not (uiop:command-line-arguments)))
|
|
(opts:describe :usage-of "timecalc"
|
|
:args "TIME"
|
|
:available-options-label "Options")
|
|
(uiop:quit 0))
|
|
|
|
(when (getf opts :version)
|
|
(format t "timecalc v~A~%" #.(asdf:component-version (asdf:find-system :timecalc)))
|
|
(uiop:quit 0))))
|
|
|
|
(handler-case
|
|
(with-user-abort
|
|
(multiple-value-bind (opts args) (get-opts)
|
|
(when (getf opts :load)
|
|
(unless (uiop:directory-exists-p (getf opts :load))
|
|
(signal 'timecalc-signal
|
|
:message "specified directory does not exist: ~A"
|
|
:args (list (getf opts :load))))
|
|
(reload-models (getf opts :load)))
|
|
|
|
(when (getf opts :web)
|
|
(let ((port (getf opts :port 9001)))
|
|
(start-server port)
|
|
(uiop:quit 0)))
|
|
|
|
(unless args
|
|
(signal 'timecalc-signal :message "please provide a timestring to convert"))
|
|
|
|
(let ((from (getf opts :from "gts"))
|
|
(to (getf opts :to)))
|
|
(format t "~A" (convert (first args) from to)))))
|
|
|
|
;; catches ctrl-c
|
|
(user-abort ()
|
|
(uiop:quit 0))
|
|
|
|
;; catches our custom condition for easier error printing
|
|
(timecalc-signal (s)
|
|
(apply #'format `(t ,(message s) ,@(signal-args s)))
|
|
(uiop:quit 2))
|
|
|
|
;; catches missing arguments for cmd line options
|
|
(opts:missing-arg (c)
|
|
(format t "~A~%" c)
|
|
(uiop:quit 1))
|
|
|
|
;; catches missing options that are required
|
|
(opts:missing-required-option (c)
|
|
(format t "~A~%" c)
|
|
(uiop:quit 1))
|
|
|
|
;; catches any and everything else :relieved:
|
|
(error (e)
|
|
(format t "encountered error:~%~A~%" e)
|
|
(uiop:quit 1))))
|