This repository has been archived by the owner on Feb 9, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cling.scm
121 lines (104 loc) · 3.77 KB
/
cling.scm
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
(module
cling
(
*program-name*
*usage*
*help-output-port*
arg
cling
help
process-arguments
usage
)
(import
scheme
(only chicken.base alist-ref current-error-port cute foldl make-parameter o print)
(only chicken.port with-output-to-port)
(only chicken.process-context command-line-arguments program-name))
(import
(only fmt dsp fmt fmt-join tabular)
(only optimism parse-command-line)
(only srfi-1 map)
(only srfi-13 string-upcase)
(only typed-records defstruct))
(define (usage port #!optional (pn (*program-name*)))
(with-output-to-port
port
(lambda ()
(print pn " [OPTION ...] [--] [ARG ...]"))))
(define *usage* (make-parameter usage))
(define *program-name* (make-parameter (program-name)))
(define *help-output-port* (make-parameter (current-error-port)))
(define (kons-default ret switch args) ret)
(defstruct arg switches help kons)
(defstruct cling grammar help konses rest-kons)
(define (arg switches #!key (help "") (kons kons-default))
(make-arg #:switches (cons (smth->list (car switches)) (cdr switches))
#:help help
#:kons kons))
(define make-help-entry cons)
(define help-entry-text car)
(define help-entry-switches/args cdr)
(define (cling #!optional rest-kons #!rest args)
(define (get-help arg)
(let ((sa (arg-switches arg)))
(make-help-entry
(arg-help arg)
`(,@(map symbol->string (car sa))
,@(map (o string-upcase symbol->string)
(smth->list (cdr sa)))))))
(define (get-kons arg)
(cons (car (arg-switches arg))
(arg-kons arg)))
(let* ((rest-kons/args ; Get optional positional arguments handler
(if (and (not (arg? rest-kons))
(procedure? rest-kons))
(cons rest-kons args)
(cons kons-default args)))
(rest-kons (car rest-kons/args))
(args (cdr rest-kons/args))
(grammar (map arg-switches args))
(help (map get-help args))
(konses (map get-kons args)))
(make-cling #:grammar grammar
#:help help
#:konses konses
#:rest-kons rest-kons)))
(define (singl x) `(,x))
(define (smth->list smth)
(if (or (pair? smth)
(null? smth))
smth
(singl smth)))
(define (help cling #!optional (pn (*program-name*)))
(define (get-switches/args-column ret)
(let* ((ret (map help-entry-switches/args ret))
(ret (map (cute fmt-join dsp <> " ") ret))
(ret (fmt-join dsp ret "\n")))
ret))
(define (get-text-column ret)
(let* ((ret (map help-entry-text ret))
(ret (fmt-join dsp ret "\n")))
ret))
(let* ((port (*help-output-port*))
(help (cling-help cling))
(usage (*usage*))
(switches/args-column (get-switches/args-column help))
(text-column (get-text-column help)))
(usage port pn)
(newline port)
(fmt port (tabular switches/args-column "\t" text-column))
(newline port)))
(define (process-arguments cling knil #!optional (args (command-line-arguments)))
(define ((make-kons konses rest-kons) ret opt)
(let ((switch (car opt))
(args (cdr opt)))
(if (eq? switch '--)
(rest-kons ret switch args)
(let ((kons (alist-ref switch konses memq kons-default)))
(kons ret switch args)))))
(let* ((grammar (cling-grammar cling))
(konses (cling-konses cling))
(pargs (parse-command-line args grammar))
(kons (make-kons konses (cling-rest-kons cling))))
(foldl kons knil pargs))))