-
-
Notifications
You must be signed in to change notification settings - Fork 86
/
clackup.ros
executable file
·109 lines (94 loc) · 3.44 KB
/
clackup.ros
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
#!/bin/sh
#|-*- mode:lisp -*-|#
#|
exec ros -Q -- $0 "$@"
|#
#|
A command-line interface for clack:clackup.
|#
(ql:quickload '(:uiop :split-sequence) :silent t)
(import 'split-sequence:split-sequence)
(defun help ()
(format t "~&Usage:
# run the .lisp file
~A hello.lisp
# switch server handler with --server
~:*~A --server wookie --port 8080 hello.lisp
"
(read-from-string
(second (assoc "script"
(let ((*read-eval*))
(read-from-string (uiop:getenv "ROS_OPTS")))
:test 'equal)))))
(defun terminate (code &optional message args)
(when message
(format *error-output* "~&Error: ~A~%"
(apply #'format nil (princ-to-string message) args)))
(uiop:quit code))
(defun starts-with (x starts)
(and (<= (length starts) (length x))
(string= x starts :end1 (length starts))))
(defun parse-args (args)
(flet ((parse-value (value)
(or (ignore-errors
(let ((read-value (read-from-string value)))
(if (and (symbolp read-value)
(not (keywordp read-value)))
value
read-value)))
value)))
(loop with app-file = nil
for option = (pop args)
for value = (pop args)
while option
if (not (starts-with option "--"))
do (if app-file
(error "Invalid option: ~S" option)
(progn
(setf app-file option)
(push value args)))
else if (string-equal option "--server")
append (list :server
(let ((parsed (parse-value value)))
(if (keywordp parsed)
parsed
(intern (string-upcase value) :keyword))))
into key-args
else
append (list (intern (string-upcase (subseq option 2)) :keyword)
(parse-value value))
into key-args
finally
(return (values app-file key-args)))))
(defun parse-server-starter-port ()
(flet ((parse-host-port (host-port)
(parse-integer
(let ((colon-pos (position #\: host-port)))
(if colon-pos
(subseq host-port (1+ colon-pos))
host-port)))))
(let ((ss-ports (uiop:getenv "SERVER_STARTER_PORT")))
(when (stringp ss-ports)
(destructuring-bind (host-port fd)
(split-sequence #\=
;; Assuming the first binding is for the Clack web server.
(car (split-sequence #\; ss-ports :count 1)))
(values (parse-host-port host-port)
(parse-integer fd)))))))
(defun main (&rest args)
(unless args
(help)
(uiop:quit -1))
(ql:quickload :clack :silent t)
(multiple-value-bind (app-file key-args)
(parse-args args)
(unless (probe-file app-file)
(terminate -1 "File doesn't exist: ~A" app-file))
;; Add :port and :fd from Server::Starter's environment var.
(multiple-value-bind (port fd)
(parse-server-starter-port)
(when port
(setf key-args (append args (list :port port :fd fd)))))
;; Disable threads
(setf (getf key-args :use-thread) nil)
(apply (intern (string :clackup) :clack) app-file key-args)))