-
Notifications
You must be signed in to change notification settings - Fork 3
/
cli.ss
57 lines (49 loc) · 2.42 KB
/
cli.ss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
(export #t)
(import
(only-in :std/generic defmethod)
(only-in :std/cli/getopt getopt getopt-parse getopt-display-help flag option
->getopt-spec call-with-processed-command-line call-with-getopt-parse)
(only-in :std/cli/multicall current-program-string)
(only-in :std/misc/list flatten)
(only-in :std/sugar awhen)
(only-in :clan/cli getopt-spec/backtrace process-opts/backtrace)
(only-in :clan/hash hash-removed)
(only-in :clan/list pair-tree-for-each!)
(only-in :clan/path-config set-path-config-root!)
(only-in ./object .has? .@ object)
(only-in ./brace @method))
(defmethod (->getopt-spec (x object))
(cond
((.has? x .type .getopt-spec) (->getopt-spec ((.@ x .type .getopt-spec) x)))
((.has? x getopt-spec) (->getopt-spec (.@ x getopt-spec)))
(else (error "No getopt-spec" x))))
(defmethod (call-with-processed-command-line (x object) (command-line :t) (function :t))
(def process-opts
(cond
((.has? x .type .process-opts) ((.@ x .type .process-opts) x))
((.has? x process-opts) (.@ x process-opts))
(else (error "No getopt-spec" x))))
(def gopt (apply getopt (->getopt-spec x)))
(def h (getopt-parse gopt command-line))
(pair-tree-for-each! process-opts (cut <> h))
(call-with-getopt-parse gopt h function))
(def options/base {getopt-spec: ? [] process-opts: ? []})
(def (make-options getopt-spec_ (process-opts_ []) (super options/base))
{(:: @ super)
getopt-spec: => (cut cons <> getopt-spec_)
process-opts: => (cut cons <> process-opts_)})
(def options/backtrace (make-options getopt-spec/backtrace process-opts/backtrace))
(def options/path-config-root
(make-options [(option 'path-config-root "--path-config-root"
help: "Directory under which to configure all runtime paths")]
[(lambda (opt) (awhen (it (hash-removed opt 'path-config-root))
(set-path-config-root! it)))]))
(def options/help
{(:: @ [options/base])
getopt-spec: => (cut cons <> (flag 'help "-h" "--help" help: "Show help")) ;; or should it be -? or both?
process-opts: => (cut cons <>
(lambda (opt) (when (hash-get opt 'help)
(let (gopt (apply getopt (flatten getopt-spec)))
(getopt-display-help gopt (current-program-string))
(force-output)
(exit 0)))))})