##// END OF EJS Templates
Remove qlot
naryl -
r52:42f15972 default
parent child Browse files
Show More
@@ -0,0 +1,4 b''
1
2 1. Install sbcl using your distribution's package manager, or download it from https://sbcl.org
3 2. Install quicklisp from https://quicklisp.org E.g. `wget https://beta.quicklisp.org/quicklisp.lisp && sbcl --load quicklisp.org` then follow instructions.
4 3. `make`
@@ -1,7 +1,8 b''
1 .*~
1 .*~
2 .qlot
2 .qlot
3 .html
3 .html
4 .png
4 .png
5 .orig
5 tests
6 tests
6 sugar-qsp
7 txt2web
7 sugar-qsp.tar.xz
8 txt2web.tar.xz
@@ -1,39 +1,32 b''
1
1
2 BIN = txt2web
2 BIN = txt2web
3 DIST = $(BIN).tar.xz
3 DIST = $(BIN).tar.xz
4
4
5 all: $(BIN)
5 all: $(BIN)
6
6
7 dist: $(DIST)
7 dist: $(DIST)
8
8
9 graphs: diagrams.png
9 graphs: diagrams.png
10
10
11 $(BIN): *.asd src/*.lisp src/*.ps strings/*.sexp
11 $(BIN): *.asd src/*.lisp src/*.ps strings/*.sexp
12 sbcl --load build.lisp -- $(BIN)
12 sbcl --load build.lisp -- $(BIN)
13
13
14 install-deps:
15 sbcl --load install-deps.lisp
16
17 update-deps:
18 sbcl --load update-deps.lisp
19
20 %.png: %.dot
14 %.png: %.dot
21 dot $< -T png -o $@
15 dot $< -T png -o $@
22
16
23 $(DIST): $(BIN) extras/*
17 $(DIST): $(BIN) extras/*
24 tar cfvJ $@ $< extras
18 tar cfvJ $@ $< extras
25
19
26 upload: $(DIST)
20 upload: $(DIST)
27 curl --upload-file $(DIST) https://transfer.sh/$(DIST)
21 curl --upload-file $(DIST) https://transfer.sh/$(DIST)
28 @echo
22 @echo
29
23
30 distclean: clean clean-deps
31
32 clean:
24 clean:
33 rm -f $(BIN) $(DIST)
25 rm -f $(BIN) $(DIST)
34
26
35 clean-deps:
27 clean-cache:
36 -rm qlfile.lock
28 -rm -rf ~/.cache/common-lisp
37 -rm -rf .qlot
38
29
39 .PHONY: all graphs install-deps update-deps clean upload
30 fresh: clean clean-cache all
31
32 .PHONY: all graphs upload clean clean-cache fresh
@@ -1,10 +1,4 b''
1 (let ((root (asdf:system-source-directory :txt2web)))
1 (ql:quickload :txt2web)
2 (asdf:initialize-source-registry
3 `(:source-registry
4 :ignore-inherited-configuration
5 (:directory ,root)
6 (:tree ,(format nil "~A~A" root ".qlot/dists")))))
7
2
8 (asdf:load-system :txt2web)
9 (uiop:register-image-restore-hook 'txt2web::entry-point-no-args nil)
3 (uiop:register-image-restore-hook 'txt2web::entry-point-no-args nil)
10 (uiop:dump-image "txt2web" :executable t)
4 (uiop:dump-image "txt2web" :executable t)
@@ -1,531 +1,531 b''
1
1
2 (in-package txt2web)
2 (in-package txt2web)
3
3
4 ;;; API deals with DOM manipulation and some bookkeeping for the
4 ;;; API deals with DOM manipulation and some bookkeeping for the
5 ;;; intrinsics, namely variables
5 ;;; intrinsics, namely variables
6 ;;; API is an implementation detail and has no QSP documentation. It
6 ;;; API is an implementation detail and has no QSP documentation. It
7 ;;; doesn't call intrinsics
7 ;;; doesn't call intrinsics
8
8
9 ;;; Utils
9 ;;; Utils
10
10
11 (defun make-act-html (title img)
11 (defun make-act-html (title img)
12 (+ "<a class='qsp-act' href='" (href-call call-act title) "' onmouseover='" (inline-call select-act title) "'>"
12 (+ "<a class='qsp-act' href='" (href-call call-act title) "' onmouseover='" (inline-call select-act title) "'>"
13 (if img (+ "<img src='" img "'>") "")
13 (if img (+ "<img src='" img "'>") "")
14 title
14 title
15 "</a>"))
15 "</a>"))
16
16
17 (defun make-menu-item-html (num title img loc)
17 (defun make-menu-item-html (num title img loc)
18 (+ "<a href='" (href-call finish-menu loc) "'>"
18 (+ "<a href='" (href-call finish-menu loc) "'>"
19 (if img (+ "<img src='" img "'>") "")
19 (if img (+ "<img src='" img "'>") "")
20 title
20 title
21 "</a>"))
21 "</a>"))
22
22
23 (defun make-obj (title img selected)
23 (defun make-obj (title img selected)
24 (+ "<li onclick='" (inline-call select-obj title img) "'>"
24 (+ "<li onclick='" (inline-call select-obj title img) "'>"
25 "<a class='qsp-obj" (if selected " qsp-obj-selected" "") "'>"
25 "<a class='qsp-obj" (if selected " qsp-obj-selected" "") "'>"
26 (if img (+ "<img src='" img "'>") "")
26 (if img (+ "<img src='" img "'>") "")
27 title
27 title
28 "</a>"))
28 "</a>"))
29
29
30 (defun make-menu-delimiter ()
30 (defun make-menu-delimiter ()
31 "<hr>")
31 "<hr>")
32
32
33 (defun copy-obj (obj)
33 (defun copy-obj (obj)
34 (chain *j-s-o-n (parse (chain *j-s-o-n (stringify obj)))))
34 (chain *j-s-o-n (parse (chain *j-s-o-n (stringify obj)))))
35
35
36 (defun report-error (text)
36 (defun report-error (text)
37 (alert text))
37 (alert text))
38
38
39 (defun start-sleeping ()
39 (defun start-sleeping ()
40 (chain (by-id "qsp") class-list (add "disable")))
40 (chain (by-id "qsp") class-list (add "disable")))
41
41
42 (defun finish-sleeping ()
42 (defun finish-sleeping ()
43 (chain (by-id "qsp") class-list (remove "disable")))
43 (chain (by-id "qsp") class-list (remove "disable")))
44
44
45 (defun sleep (msec)
45 (defun sleep (msec)
46 (with-sleep (resume)
46 (with-sleep (resume)
47 (set-timeout resume msec)))
47 (set-timeout resume msec)))
48
48
49 (defun init-dom ()
49 (defun init-dom ()
50 ;; Save/load buttons
50 ;; Save/load buttons
51 (let ((btn (by-id "qsp-btn-save")))
51 (let ((btn (by-id "qsp-btn-save")))
52 (setf (@ btn onclick) savegame)
52 (setf (@ btn onclick) savegame)
53 (setf (@ btn href) "#"))
53 (setf (@ btn href) "#"))
54 (let ((btn (by-id "qsp-btn-open")))
54 (let ((btn (by-id "qsp-btn-open")))
55 (setf (@ btn onclick) opengame)
55 (setf (@ btn onclick) opengame)
56 (setf (@ btn href) "#"))
56 (setf (@ btn href) "#"))
57 ;; Close image on click
57 ;; Close image on click
58 (setf (@ (by-id "qsp-image-container") onclick)
58 (setf (@ (by-id "qsp-image-container") onclick)
59 show-image)
59 show-image)
60 ;; Enter in input field
60 ;; Enter in input field
61 (setf (@ (get-frame :input) onkeyup)
61 (setf (@ (get-frame :input) onkeyup)
62 on-input-key)
62 on-input-key)
63 ;; Close the dropdown on any click
63 ;; Close the dropdown on any click
64 (setf (@ window onclick)
64 (setf (@ window onclick)
65 (lambda (event)
65 (lambda (event)
66 (setf (@ window mouse)
66 (setf (@ window mouse)
67 (list (@ event page-x)
67 (list (@ event page-x)
68 (@ event page-y)))
68 (@ event page-y)))
69 (finish-menu nil))))
69 (finish-menu nil))))
70
70
71 (defun call-serv-loc (var-name &rest args)
71 (defun call-serv-loc (var-name &rest args)
72 (let ((loc-name (get-global var-name 0)))
72 (let ((loc-name (get-global var-name 0)))
73 (when loc-name
73 (when loc-name
74 (let ((loc (getprop *locs loc-name)))
74 (let ((loc (getprop *locs loc-name)))
75 (when loc
75 (when loc
76 (call-loc loc-name args))))))
76 (call-loc loc-name args))))))
77
77
78 (defun filename-game (filename)
78 (defun filename-game (filename)
79 (let ((game-name (chain filename (match "(.*/)?([^.]+)(\\.[a-zA-Z]+)?") 2))))
79 (let ((game-name (chain filename (match "(.*/)?([^.]+)(\\.[a-zA-Z]+)?") 2))))
80 (getprop *games game-name))
80 (getprop *games game-name))
81
81
82 (defun run-game (name)
82 (defun run-game (name)
83 (let ((game (filename-game name)))
83 (let ((game (filename-game name)))
84 (setf *main-game name)
84 (setf *main-game name)
85 ;; Replace locations with the new game's
85 ;; Replace locations with the new game's
86 (setf *locs game)
86 (setf *locs game)
87 (funcall (getprop game
87 (funcall (getprop game
88 (chain *object (keys game) 0))
88 (chain *object (keys game) 0))
89 (list))))
89 (list))))
90
90
91 ;;; Misc
91 ;;; Misc
92
92
93 (defun newline (key)
93 (defun newline (key)
94 (append-id (key-to-id key) "<br>" t))
94 (append-id (key-to-id key) "<br>" t))
95
95
96 (defun clear-id (id)
96 (defun clear-id (id)
97 (setf (inner-html (by-id id)) ""))
97 (setf (inner-html (by-id id)) ""))
98
98
99 (defun escape-html (text)
99 (defun escape-html (text)
100 (chain text
100 (chain text
101 (replace (regex "/&/g") "&amp;")
101 (replace (regex "/&/g") "&amp;")
102 (replace (regex "/</g") "&lt;")
102 (replace (regex "/</g") "&lt;")
103 (replace (regex "/>/g") "&gt;")
103 (replace (regex "/>/g") "&gt;")
104 (replace (regex "/\"/g") "&quot;")
104 (replace (regex "/\"/g") "&quot;")
105 (replace (regex "/'/g") "&apos;")))
105 (replace (regex "/'/g") "&apos;")))
106
106
107 (defun prepare-contents (s &optional force-html)
107 (defun prepare-contents (s &optional force-html)
108 (setf s (chain s (to-string)))
108 (setf s (chain s (to-string)))
109 (if (or force-html (get-global "USEHTML" 0))
109 (if (or force-html (get-global "USEHTML" 0))
110 s
110 s
111 (escape-html s)))
111 (escape-html s)))
112
112
113 (defun get-id (id &optional force-html)
113 (defun get-id (id &optional force-html)
114 (inner-html (by-id id)))
114 (inner-html (by-id id)))
115
115
116 (defun set-id (id contents &optional force-html)
116 (defun set-id (id contents &optional force-html)
117 (setf (inner-html (by-id id)) (prepare-contents contents force-html)))
117 (setf (inner-html (by-id id)) (prepare-contents contents force-html)))
118
118
119 (defun append-id (id contents &optional force-html)
119 (defun append-id (id contents &optional force-html)
120 (when contents
120 (when contents
121 (incf (inner-html (by-id id)) (prepare-contents contents force-html))))
121 (incf (inner-html (by-id id)) (prepare-contents contents force-html))))
122
122
123 (defun on-input-key (ev)
123 (defun on-input-key (ev)
124 (when (= 13 (@ ev key-code))
124 (when (= 13 (@ ev key-code))
125 (chain ev (prevent-default))
125 (chain ev (prevent-default))
126 (call-serv-loc "$USERCOM")))
126 (call-serv-loc "$USERCOM")))
127
127
128 ;;; Function calls
128 ;;; Function calls
129
129
130 (defun init-args (args)
130 (defun init-args (args)
131 (dotimes (i (length args))
131 (dotimes (i (length args))
132 (let ((arg (elt args i)))
132 (let ((arg (elt args i)))
133 (if (numberp arg)
133 (if (numberp arg)
134 (set-var args i :num arg)
134 (set-var args i :num arg)
135 (set-var args i :str arg)))))
135 (set-var args i :str arg)))))
136
136
137 (defun get-result ()
137 (defun get-result ()
138 (or (get-global "$RESULT" 0)
138 (or (get-global "$RESULT" 0)
139 (get-global "RESULT" 0)))
139 (get-global "RESULT" 0)))
140
140
141 (defun call-loc (name args)
141 (defun call-loc (name args)
142 (setf name (chain name (to-upper-case)))
142 (setf name (chain name (to-upper-case)))
143 (with-frame
143 (with-frame
144 (with-call-args args
144 (with-call-args args
145 (funcall (getprop *locs name))))
145 (funcall (getprop *locs name))))
146 (void))
146 (void))
147
147
148 (defun call-act (title)
148 (defun call-act (title)
149 (with-frame
149 (with-frame
150 (funcall (getprop *acts title :act)))
150 (funcall (getprop *acts title :act)))
151 (void))
151 (void))
152
152
153 ;;; Text windows
153 ;;; Text windows
154
154
155 (defun key-to-id (key)
155 (defun key-to-id (key)
156 (case key
156 (case key
157 (:all "qsp")
157 (:all "qsp")
158 (:main "qsp-main")
158 (:main "qsp-main")
159 (:stat "qsp-stat")
159 (:stat "qsp-stat")
160 (:objs "qsp-objs")
160 (:objs "qsp-objs")
161 (:acts "qsp-acts")
161 (:acts "qsp-acts")
162 (:input "qsp-input")
162 (:input "qsp-input")
163 (:image "qsp-image")
163 (:image "qsp-image")
164 (:dropdown "qsp-dropdown")
164 (:dropdown "qsp-dropdown")
165 (t (report-error "Internal error!"))))
165 (t (report-error "Internal error!"))))
166
166
167 (defun get-frame (key)
167 (defun get-frame (key)
168 (by-id (key-to-id key)))
168 (by-id (key-to-id key)))
169
169
170 (defun add-text (key text)
170 (defun add-text (key text)
171 (append-id (key-to-id key) text))
171 (append-id (key-to-id key) text))
172
172
173 (defun get-text (key)
173 (defun get-text (key)
174 (get-id (key-to-id key)))
174 (get-id (key-to-id key)))
175
175
176 (defun clear-text (key)
176 (defun clear-text (key)
177 (clear-id (key-to-id key)))
177 (clear-id (key-to-id key)))
178
178
179 (defun enable-frame (key enable)
179 (defun enable-frame (key enable)
180 (let ((obj (get-frame key)))
180 (let ((obj (get-frame key)))
181 (setf (@ obj style display) (if enable "block" "none"))
181 (setf (@ obj style display) (if enable "block" "none"))
182 (void)))
182 (void)))
183
183
184 ;;; Actions
184 ;;; Actions
185
185
186 (defun add-act (title img act)
186 (defun add-act (title img act)
187 (setf (getprop *acts title)
187 (setf (getprop *acts title)
188 (create :title title :img img :act act :selected nil))
188 (create :title title :img img :act act :selected nil))
189 (update-acts))
189 (update-acts))
190
190
191 (defun del-act (title)
191 (defun del-act (title)
192 (delete (getprop *acts title))
192 (delete (getprop *acts title))
193 (update-acts))
193 (update-acts))
194
194
195 (defun clear-act ()
195 (defun clear-act ()
196 (setf *acts (create))
196 (setf *acts (create))
197 (update-acts))
197 (update-acts))
198
198
199 (defun update-acts ()
199 (defun update-acts ()
200 (clear-id "qsp-acts")
200 (clear-id "qsp-acts")
201 (let ((elt (by-id "qsp-acts")))
201 (let ((elt (by-id "qsp-acts")))
202 (for-in (title *acts)
202 (for-in (title *acts)
203 (let ((obj (getprop *acts title)))
203 (let ((obj (getprop *acts title)))
204 (incf (inner-html elt) (make-act-html title (getprop obj :img)))))))
204 (incf (inner-html elt) (make-act-html title (getprop obj :img)))))))
205
205
206 (defun select-act (title)
206 (defun select-act (title)
207 (loop :for (k v) :of *acts
207 (loop :for (k v) :of *acts
208 :do (setf (getprop v :selected) nil))
208 :do (setf (getprop v :selected) nil))
209 (setf (getprop *acts title :selected) t)
209 (setf (getprop *acts title :selected) t)
210 (call-serv-loc "$ONACTSEL"))
210 (call-serv-loc "$ONACTSEL"))
211
211
212 ;;; "Syntax"
212 ;;; "Syntax"
213
213
214 (defun qspfor (name index from to step body)
214 (defun qspfor (name index from to step body)
215 (for ((i from))
215 (ps:for ((i from))
216 ((< i to))
216 ((< i to))
217 ((incf i step))
217 ((incf i step))
218 (set-var name index :num i)
218 (set-var name index :num i)
219 (unless (await (funcall body))
219 (unless (await (funcall body))
220 (return-from qspfor))))
220 (return-from qspfor))))
221
221
222 ;;; Variables
222 ;;; Variables
223
223
224 (defun new-var (slot &rest indexes)
224 (defun new-var (slot &rest indexes)
225 (let ((v (list)))
225 (let ((v (list)))
226 (dolist (index indexes)
226 (dolist (index indexes)
227 (setf (elt v index) (if (eq #\$ (elt slot 0)) "" 0)))
227 (setf (elt v index) (if (eq #\$ (elt slot 0)) "" 0)))
228 (setf (@ v :indexes) (create))
228 (setf (@ v :indexes) (create))
229 v))
229 v))
230
230
231 (defun set-str-element (slot index value)
231 (defun set-str-element (slot index value)
232 (if (has index (getprop slot :indexes))
232 (if (has index (getprop slot :indexes))
233 (setf (elt (getprop slot)
233 (setf (elt (getprop slot)
234 (getprop slot :indexes index))
234 (getprop slot :indexes index))
235 value)
235 value)
236 (progn
236 (progn
237 (chain slot (push value))
237 (chain slot (push value))
238 (setf (elt slot index)
238 (setf (elt slot index)
239 (length slot))))
239 (length slot))))
240 (void))
240 (void))
241
241
242 (defun set-any-element (slot index value)
242 (defun set-any-element (slot index value)
243 (cond ((null index)
243 (cond ((null index)
244 (chain (elt slot) (push value)))
244 (chain (elt slot) (push value)))
245 ((numberp index)
245 ((numberp index)
246 (setf (elt slot index) value))
246 (setf (elt slot index) value))
247 ((stringp index)
247 ((stringp index)
248 (set-str-element slot index value))
248 (set-str-element slot index value))
249 (t (report-error "INTERNAL ERROR")))
249 (t (report-error "INTERNAL ERROR")))
250 (void))
250 (void))
251
251
252 (defun set-serv-var (name index value)
252 (defun set-serv-var (name index value)
253 (let ((slot (getprop *globals name)))
253 (let ((slot (getprop *globals name)))
254 (set-any-element slot index value))
254 (set-any-element slot index value))
255 (funcall (getprop serv-vars name :body) value index)
255 (funcall (getprop serv-vars name :body) value index)
256 (void))
256 (void))
257
257
258 (defun get-element (slot index)
258 (defun get-element (slot index)
259 (if (numberp index)
259 (if (numberp index)
260 (elt slot index)
260 (elt slot index)
261 (elt slot (getprop slot :indexes index))))
261 (elt slot (getprop slot :indexes index))))
262
262
263 (defun get-global (name index)
263 (defun get-global (name index)
264 (elt (getprop *globals name) index))
264 (elt (getprop *globals name) index))
265
265
266 (defun kill-var (store name &optional index)
266 (defun kill-var (store name &optional index)
267 (setf name (chain name (to-upper-case)))
267 (setf name (chain name (to-upper-case)))
268 (if (and index (not (= 0 index)))
268 (if (and index (not (= 0 index)))
269 (chain (getprop *globals name) (kill index))
269 (chain (getprop *globals name) (kill index))
270 (delete (getprop *globals name)))
270 (delete (getprop *globals name)))
271 (void))
271 (void))
272
272
273 (defun array-size (name)
273 (defun array-size (name)
274 (@ (var-ref name) :values length))
274 (@ (var-ref name) :values length))
275
275
276 ;;; Locals
276 ;;; Locals
277
277
278 (defun push-local-frame ()
278 (defun push-local-frame ()
279 (chain *locals (push (create)))
279 (chain *locals (push (create)))
280 (void))
280 (void))
281
281
282 (defun pop-local-frame ()
282 (defun pop-local-frame ()
283 (chain *locals (pop))
283 (chain *locals (pop))
284 (void))
284 (void))
285
285
286 (defun current-local-frame ()
286 (defun current-local-frame ()
287 (elt *locals (1- (length *locals))))
287 (elt *locals (1- (length *locals))))
288
288
289 ;;; Objects
289 ;;; Objects
290
290
291 (defun select-obj (title img)
291 (defun select-obj (title img)
292 (loop :for (k v) :of *objs
292 (loop :for (k v) :of *objs
293 :do (setf (getprop v :selected) nil))
293 :do (setf (getprop v :selected) nil))
294 (setf (getprop *objs title :selected) t)
294 (setf (getprop *objs title :selected) t)
295 (call-serv-loc "$ONOBJSEL" title img))
295 (call-serv-loc "$ONOBJSEL" title img))
296
296
297 (defun update-objs ()
297 (defun update-objs ()
298 (let ((elt (by-id "qsp-objs")))
298 (let ((elt (by-id "qsp-objs")))
299 (setf (inner-html elt) "<ul>")
299 (setf (inner-html elt) "<ul>")
300 (loop :for (name obj) :of *objs
300 (loop :for (name obj) :of *objs
301 :do (incf (inner-html elt)
301 :do (incf (inner-html elt)
302 (make-obj name (@ obj :img) (@ obj :selected))))
302 (make-obj name (@ obj :img) (@ obj :selected))))
303 (incf (inner-html elt) "</ul>")))
303 (incf (inner-html elt) "</ul>")))
304
304
305 ;;; Menu
305 ;;; Menu
306
306
307 (defun open-menu (menu-data)
307 (defun open-menu (menu-data)
308 (let ((elt (get-frame :dropdown))
308 (let ((elt (get-frame :dropdown))
309 (i 0))
309 (i 0))
310 (loop :for item :in menu-data
310 (loop :for item :in menu-data
311 :do (incf i)
311 :do (incf i)
312 :do (incf (inner-html elt)
312 :do (incf (inner-html elt)
313 (if (eq item :delimiter)
313 (if (eq item :delimiter)
314 (make-menu-delimiter i)
314 (make-menu-delimiter i)
315 (make-menu-item-html i
315 (make-menu-item-html i
316 (@ item :text)
316 (@ item :text)
317 (@ item :icon)
317 (@ item :icon)
318 (@ item :loc)))))
318 (@ item :loc)))))
319 (let ((mouse (@ window mouse)))
319 (let ((mouse (@ window mouse)))
320 (setf (@ elt style left) (+ (elt mouse 0) "px"))
320 (setf (@ elt style left) (+ (elt mouse 0) "px"))
321 (setf (@ elt style top) (+ (elt mouse 1) "px"))
321 (setf (@ elt style top) (+ (elt mouse 1) "px"))
322 ;; Make sure it's inside the viewport
322 ;; Make sure it's inside the viewport
323 (when (> (@ document body inner-width)
323 (when (> (@ document body inner-width)
324 (+ (elt mouse 0) (@ elt inner-width)))
324 (+ (elt mouse 0) (@ elt inner-width)))
325 (incf (@ elt style left) (@ elt inner-width)))
325 (incf (@ elt style left) (@ elt inner-width)))
326 (when (> (@ document body inner-height)
326 (when (> (@ document body inner-height)
327 (+ (elt mouse 0) (@ elt inner-height)))
327 (+ (elt mouse 0) (@ elt inner-height)))
328 (incf (@ elt style top) (@ elt inner-height))))
328 (incf (@ elt style top) (@ elt inner-height))))
329 (setf (@ elt style display) "block")))
329 (setf (@ elt style display) "block")))
330
330
331 (defun finish-menu (loc)
331 (defun finish-menu (loc)
332 (when *menu-resume
332 (when *menu-resume
333 (let ((elt (get-frame :dropdown)))
333 (let ((elt (get-frame :dropdown)))
334 (setf (inner-html elt) "")
334 (setf (inner-html elt) "")
335 (setf (@ elt style display) "none")
335 (setf (@ elt style display) "none")
336 (funcall *menu-resume)
336 (funcall *menu-resume)
337 (setf *menu-resume nil))
337 (setf *menu-resume nil))
338 (when loc
338 (when loc
339 (call-loc loc)))
339 (call-loc loc)))
340 (void))
340 (void))
341
341
342 (defun menu (menu-data)
342 (defun menu (menu-data)
343 (with-sleep (resume)
343 (with-sleep (resume)
344 (open-menu menu-data)
344 (open-menu menu-data)
345 (setf *menu-resume resume))
345 (setf *menu-resume resume))
346 (void))
346 (void))
347
347
348 ;;; Content
348 ;;; Content
349
349
350 (defun clean-audio ()
350 (defun clean-audio ()
351 (loop :for k :in (chain *object (keys *playing))
351 (loop :for k :in (chain *object (keys *playing))
352 :for v := (getprop *playing k)
352 :for v := (getprop *playing k)
353 :do (when (@ v ended)
353 :do (when (@ v ended)
354 (delete (@ *playing k)))))
354 (delete (@ *playing k)))))
355
355
356 (defun show-image (path)
356 (defun show-image (path)
357 (let ((img (get-frame :image)))
357 (let ((img (get-frame :image)))
358 (cond (path
358 (cond (path
359 (setf (@ img src) path)
359 (setf (@ img src) path)
360 (setf (@ img style display) "flex"))
360 (setf (@ img style display) "flex"))
361 (t
361 (t
362 (setf (@ img src) "")
362 (setf (@ img src) "")
363 (setf (@ img style display) "hidden")))))
363 (setf (@ img style display) "hidden")))))
364
364
365 (defun show-inline-images (frame-name images)
365 (defun show-inline-images (frame-name images)
366 (let ((frame (get-frame frame-name))
366 (let ((frame (get-frame frame-name))
367 (text ""))
367 (text ""))
368 (incf text "<div style='position:relative; display: inline-block'>")
368 (incf text "<div style='position:relative; display: inline-block'>")
369 (incf text (+ "<img src='" (@ images 0) "'>"))
369 (incf text (+ "<img src='" (@ images 0) "'>"))
370 (loop :for image :in (chain images (slice 1))
370 (loop :for image :in (chain images (slice 1))
371 :do (incf text
371 :do (incf text
372 (+ "<img style='position:absolute' src='" image "'>")))
372 (+ "<img style='position:absolute' src='" image "'>")))
373 (incf text "</div>")
373 (incf text "</div>")
374 (incf (inner-html frame) text)))
374 (incf (inner-html frame) text)))
375
375
376 (defun rgb-string (rgb)
376 (defun rgb-string (rgb)
377 (let ((red (ps::>> rgb 16))
377 (let ((red (ps::>> rgb 16))
378 (green (logand (ps::>> rgb 8) 255))
378 (green (logand (ps::>> rgb 8) 255))
379 (blue (logand rgb 255)))
379 (blue (logand rgb 255)))
380 (flet ((rgb-to-hex (comp)
380 (flet ((rgb-to-hex (comp)
381 (let ((hex (chain (*number comp) (to-string 16))))
381 (let ((hex (chain (*number comp) (to-string 16))))
382 (if (< (length hex) 2)
382 (if (< (length hex) 2)
383 (+ "0" hex)
383 (+ "0" hex)
384 hex))))
384 hex))))
385 (+ "#" (rgb-to-hex red) (rgb-to-hex green) (rgb-to-hex blue)))))
385 (+ "#" (rgb-to-hex red) (rgb-to-hex green) (rgb-to-hex blue)))))
386
386
387 (defun store-obj (key obj)
387 (defun store-obj (key obj)
388 (store-str key (btoa (encode-u-r-i-component (chain *j-s-o-n (stringify obj)))))
388 (store-str key (btoa (encode-u-r-i-component (chain *j-s-o-n (stringify obj)))))
389 (void))
389 (void))
390 (defun store-str (key str)
390 (defun store-str (key str)
391 (chain local-storage (set-item (+ "qsp_" key) str))
391 (chain local-storage (set-item (+ "qsp_" key) str))
392 (void))
392 (void))
393
393
394 (defun load-obj (key)
394 (defun load-obj (key)
395 (chain *j-s-o-n (parse (encode-u-r-i-component (atob (load-str key))))))
395 (chain *j-s-o-n (parse (encode-u-r-i-component (atob (load-str key))))))
396 (defun load-str (key)
396 (defun load-str (key)
397 (chain local-storage (get-item (+ "qsp_" key))))
397 (chain local-storage (get-item (+ "qsp_" key))))
398
398
399 ;;; Saves
399 ;;; Saves
400
400
401 (defun slot-savegame (slot comment)
401 (defun slot-savegame (slot comment)
402 (let ((saves (load-obj "saves")))
402 (let ((saves (load-obj "saves")))
403 (setf (@ saves slot) comment)
403 (setf (@ saves slot) comment)
404 (store-obj saves))
404 (store-obj saves))
405 (store-str slot (state-to-base64))
405 (store-str slot (state-to-base64))
406 (void))
406 (void))
407
407
408 (defun slot-loadgame (slot)
408 (defun slot-loadgame (slot)
409 (base64-to-state (load-str slot))
409 (base64-to-state (load-str slot))
410 (void))
410 (void))
411
411
412 (defun slot-deletegame (slot)
412 (defun slot-deletegame (slot)
413 (let ((saves (load-obj "saves")))
413 (let ((saves (load-obj "saves")))
414 (setf (@ saves slot) undefined)
414 (setf (@ saves slot) undefined)
415 (store-obj saves))
415 (store-obj saves))
416 (store-str slot undefined)
416 (store-str slot undefined)
417 (void))
417 (void))
418
418
419 (defun slot-listgames ()
419 (defun slot-listgames ()
420 (load-obj "saves"))
420 (load-obj "saves"))
421
421
422 (defun opengame ()
422 (defun opengame ()
423 (let ((element (chain document (create-element :input))))
423 (let ((element (chain document (create-element :input))))
424 (chain element (set-attribute :type :file))
424 (chain element (set-attribute :type :file))
425 (chain element (set-attribute :id :qsp-opengame))
425 (chain element (set-attribute :id :qsp-opengame))
426 (chain element (set-attribute :tabindex -1))
426 (chain element (set-attribute :tabindex -1))
427 (chain element (set-attribute "aria-hidden" t))
427 (chain element (set-attribute "aria-hidden" t))
428 (setf (@ element style display) :block)
428 (setf (@ element style display) :block)
429 (setf (@ element style visibility) :hidden)
429 (setf (@ element style visibility) :hidden)
430 (setf (@ element style position) :fixed)
430 (setf (@ element style position) :fixed)
431 (setf (@ element onchange)
431 (setf (@ element onchange)
432 (lambda (event)
432 (lambda (event)
433 (let* ((file (@ event target files 0))
433 (let* ((file (@ event target files 0))
434 (reader (new (*file-reader))))
434 (reader (new (*file-reader))))
435 (setf (@ reader onload)
435 (setf (@ reader onload)
436 (lambda (ev)
436 (lambda (ev)
437 (block nil
437 (block nil
438 (let ((target (@ ev current-target)))
438 (let ((target (@ ev current-target)))
439 (unless (@ target result)
439 (unless (@ target result)
440 (return))
440 (return))
441 (base64-to-state (@ target result))
441 (base64-to-state (@ target result))
442 (unstash-state)))))
442 (unstash-state)))))
443 (chain reader (read-as-text file)))))
443 (chain reader (read-as-text file)))))
444 (chain document body (append-child element))
444 (chain document body (append-child element))
445 (chain element (click))
445 (chain element (click))
446 (chain document body (remove-child element))))
446 (chain document body (remove-child element))))
447
447
448 (defun savegame ()
448 (defun savegame ()
449 (let ((element (chain document (create-element :a))))
449 (let ((element (chain document (create-element :a))))
450 (chain element (set-attribute :href (+ "data:text/plain;charset=utf-8," (state-to-base64))))
450 (chain element (set-attribute :href (+ "data:text/plain;charset=utf-8," (state-to-base64))))
451 (chain element (set-attribute :download "savegame.sav"))
451 (chain element (set-attribute :download "savegame.sav"))
452 (setf (@ element style display) :none)
452 (setf (@ element style display) :none)
453 (chain document body (append-child element))
453 (chain document body (append-child element))
454 (chain element (click))
454 (chain element (click))
455 (chain document body (remove-child element))))
455 (chain document body (remove-child element))))
456
456
457 (defun stash-state (args)
457 (defun stash-state (args)
458 (call-serv-loc "$ONGSAVE")
458 (call-serv-loc "$ONGSAVE")
459 (setf *state-stash
459 (setf *state-stash
460 (chain *j-s-o-n (stringify
460 (chain *j-s-o-n (stringify
461 (create :vars *globals
461 (create :vars *globals
462 :objs *objs
462 :objs *objs
463 :loc-args args
463 :loc-args args
464 :msecs (- (chain *date (now)) *started-at)
464 :msecs (- (chain *date (now)) *started-at)
465 :timer-interval *timer-interval
465 :timer-interval *timer-interval
466 :main-html (inner-html
466 :main-html (inner-html
467 (get-frame :main))
467 (get-frame :main))
468 :stat-html (inner-html
468 :stat-html (inner-html
469 (get-frame :stat))
469 (get-frame :stat))
470 :next-location *current-location))))
470 :next-location *current-location))))
471 (void))
471 (void))
472
472
473 (defun unstash-state ()
473 (defun unstash-state ()
474 (let ((data (chain *j-s-o-n (parse *state-stash))))
474 (let ((data (chain *j-s-o-n (parse *state-stash))))
475 (clear-act)
475 (clear-act)
476 (setf *globals (@ data :vars))
476 (setf *globals (@ data :vars))
477 (loop :for k :in (chain *object (keys *globals))
477 (loop :for k :in (chain *object (keys *globals))
478 :do (chain *object (set-prototype-of (getprop *globals k)
478 :do (chain *object (set-prototype-of (getprop *globals k)
479 (@ *var prototype))))
479 (@ *var prototype))))
480 (setf *started-at (- (chain *date (now)) (@ data :msecs)))
480 (setf *started-at (- (chain *date (now)) (@ data :msecs)))
481 (setf *objs (@ data :objs))
481 (setf *objs (@ data :objs))
482 (setf *current-location (@ data :next-location))
482 (setf *current-location (@ data :next-location))
483 (setf (inner-html (get-frame :main))
483 (setf (inner-html (get-frame :main))
484 (@ data :main-html))
484 (@ data :main-html))
485 (setf (inner-html (get-frame :stat))
485 (setf (inner-html (get-frame :stat))
486 (@ data :stat-html))
486 (@ data :stat-html))
487 (update-objs)
487 (update-objs)
488 (set-timer (@ data :timer-interval))
488 (set-timer (@ data :timer-interval))
489 (call-serv-loc "$ONGLOAD")
489 (call-serv-loc "$ONGLOAD")
490 (call-loc *current-location (@ data :loc-args))
490 (call-loc *current-location (@ data :loc-args))
491 (void)))
491 (void)))
492
492
493 (defun state-to-base64 ()
493 (defun state-to-base64 ()
494 (btoa (encode-u-r-i-component *state-stash)))
494 (btoa (encode-u-r-i-component *state-stash)))
495
495
496 (defun base64-to-state (data)
496 (defun base64-to-state (data)
497 (setf *state-stash (decode-u-r-i-component (atob data))))
497 (setf *state-stash (decode-u-r-i-component (atob data))))
498
498
499 ;;; Timers
499 ;;; Timers
500
500
501 (defun set-timer (interval)
501 (defun set-timer (interval)
502 (setf *timer-interval interval)
502 (setf *timer-interval interval)
503 (clear-interval *timer-obj)
503 (clear-interval *timer-obj)
504 (setf *timer-obj
504 (setf *timer-obj
505 (set-interval
505 (set-interval
506 (lambda ()
506 (lambda ()
507 (call-serv-loc "$COUNTER"))
507 (call-serv-loc "$COUNTER"))
508 interval)))
508 interval)))
509
509
510 ;;; Special variables
510 ;;; Special variables
511
511
512 (defvar serv-vars (create))
512 (defvar serv-vars (create))
513
513
514 (define-serv-var $backimage (path)
514 (define-serv-var $backimage (path)
515 (setf (@ (get-frame :main) style background-image) path))
515 (setf (@ (get-frame :main) style background-image) path))
516
516
517 (define-serv-var bcolor (color)
517 (define-serv-var bcolor (color)
518 (setf (@ (get-frame :all) style background-color) (rgb-string color)))
518 (setf (@ (get-frame :all) style background-color) (rgb-string color)))
519
519
520 (define-serv-var fcolor (color)
520 (define-serv-var fcolor (color)
521 (setf (@ (get-frame :all) style color) (rgb-string color)))
521 (setf (@ (get-frame :all) style color) (rgb-string color)))
522
522
523 (define-serv-var lcolor (color)
523 (define-serv-var lcolor (color)
524 (setf (@ (get-frame :style) inner-text)
524 (setf (@ (get-frame :style) inner-text)
525 (+ "a { color: " (rgb-string color) ";}")))
525 (+ "a { color: " (rgb-string color) ";}")))
526
526
527 (define-serv-var fsize (size)
527 (define-serv-var fsize (size)
528 (setf (@ (get-frame :all) style font-size) size))
528 (setf (@ (get-frame :all) style font-size) size))
529
529
530 (define-serv-var $fname (font-name)
530 (define-serv-var $fname (font-name)
531 (setf (@ (get-frame :all) style font-family) (+ font-name ",serif")))
531 (setf (@ (get-frame :all) style font-family) (+ font-name ",serif")))
@@ -1,153 +1,153 b''
1
1
2 (in-package txt2web)
2 (in-package txt2web)
3
3
4 (defvar *app-name* "")
4 (defvar *app-name* "")
5
5
6 (defun entry-point-no-args ()
6 (defun entry-point-no-args ()
7 (entry-point uiop:*command-line-arguments*))
7 (entry-point uiop:*command-line-arguments*))
8
8
9 (defun entry-point (args)
9 (defun entry-point (args)
10 (setf *app-name* (uiop:argv0))
10 (setf *app-name* (uiop:argv0))
11 (let ((*package* (find-package :txt2web)))
11 (let ((*package* (find-package :txt2web)))
12 (catch :terminate
12 (catch :terminate
13 (let ((compiler (apply #'make-instance 'compiler (parse-opts args))))
13 (let ((compiler (apply #'make-instance 'compiler (parse-opts args))))
14 (write-compiled-file compiler))))
14 (write-compiled-file compiler))))
15 (values))
15 (values))
16
16
17 (defun parse-opts (args)
17 (defun parse-opts (args)
18 (let ((mode :sources)
18 (let ((mode :sources)
19 (data (list :sources nil :target nil :js nil :css nil :body nil :compile nil :beautify nil)))
19 (data (list :sources nil :target nil :js nil :css nil :body nil :compile nil :beautify nil)))
20 (loop :for arg :in args
20 (loop :for arg :in args
21 :do (alexandria:switch (arg :test #'string=)
21 :do (alexandria:switch (arg :test #'string=)
22 ("-o" (setf mode :target))
22 ("-o" (setf mode :target))
23 ("--js" (setf mode :js))
23 ("--js" (setf mode :js))
24 ("--css" (setf mode :css))
24 ("--css" (setf mode :css))
25 ("--body" (setf mode :body))
25 ("--body" (setf mode :body))
26 ("-c" (setf (getf data :compile) t))
26 ("-c" (setf (getf data :compile) t))
27 ("--beautify" (setf (getf data :beautify) t))
27 ("--beautify" (setf (getf data :beautify) t))
28 (t (push arg (getf data mode)))))
28 (t (push arg (getf data mode)))))
29 (unless (< 0 (length (getf data :sources)))
29 (unless (< 0 (length (getf data :sources)))
30 (report-error "There should be at least one source"))
30 (report-error "There should be at least one source"))
31 (unless (> 1 (length (getf data :target)))
31 (unless (> 1 (length (getf data :target)))
32 (report-error "There should be no more than one target"))
32 (report-error "There should be no more than one target"))
33 (unless (> 1 (length (getf data :body)))
33 (unless (> 1 (length (getf data :body)))
34 (report-error "There should be no more than one body"))
34 (report-error "There should be no more than one body"))
35 (unless (getf data :target)
35 (unless (getf data :target)
36 (setf (getf data :target)
36 (setf (getf data :target)
37 (let* ((sources (first (getf data :sources)))
37 (let* ((sources (first (getf data :sources)))
38 (tokens (uiop:split-string sources :separator "."))
38 (tokens (uiop:split-string sources :separator "."))
39 (target (format nil "~{~A~^.~}.html"
39 (target (format nil "~{~A~^.~}.html"
40 (butlast tokens))))
40 (butlast tokens))))
41 (list target))))
41 (list target))))
42 (list :sources (getf data :sources)
42 (list :sources (getf data :sources)
43 :target (first (getf data :target))
43 :target (first (getf data :target))
44 :js (getf data :js)
44 :js (getf data :js)
45 :css (getf data :css)
45 :css (getf data :css)
46 :body (first (getf data :body))
46 :body (first (getf data :body))
47 :compile (getf data :compile)
47 :compile (getf data :compile)
48 :beautify (getf data :beautify))))
48 :beautify (getf data :beautify))))
49
49
50 (defun print-usage ()
50 (defun print-usage ()
51 (lformat t :usage *app-name*))
51 (lformat t :usage *app-name*))
52
52
53 (defun parse-file (filename)
53 (defun parse-file (filename)
54 (p:parse 'txt2web-grammar
54 (p:parse 'txt2web-grammar
55 (alexandria:read-file-into-string filename)))
55 (alexandria:read-file-into-string filename)))
56
56
57 (defun report-error (fmt &rest args)
57 (defun report-error (fmt &rest args)
58 (format t "ERROR: ~A~%" (apply #'format nil fmt args))
58 (format t "ERROR: ~A~%" (apply #'format nil fmt args))
59 (print-usage)
59 (print-usage)
60 (throw :terminate nil))
60 (throw :terminate nil))
61
61
62 ;;; JS
62 ;;; JS
63
63
64 (defun minify-package (package-designator minify prefix)
64 (defun minify-package (package-designator minify prefix)
65 (setf (ps:ps-package-prefix package-designator) prefix)
65 (setf (ps:ps-package-prefix package-designator) prefix)
66 (if minify
66 (if minify
67 (ps:obfuscate-package package-designator)
67 (ps:obfuscate-package package-designator)
68 (ps:unobfuscate-package package-designator)))
68 (ps:unobfuscate-package package-designator)))
69
69
70 (defmethod js-sources ((compiler compiler))
70 (defmethod js-sources ((compiler compiler))
71 (let ((ps:*ps-print-pretty* (beautify compiler)))
71 (let ((ps:*ps-print-pretty* (beautify compiler)))
72 (cond ((beautify compiler)
72 (cond ((beautify compiler)
73 (minify-package "TXT2WEB.MAIN" nil "qsp_")
73 (minify-package "TXT2WEB.MAIN" nil "qsp_")
74 (minify-package "TXT2WEB.API" nil "qsp_api_")
74 (minify-package "TXT2WEB.API" nil "qsp_api_")
75 (minify-package "TXT2WEB.LIB" nil "qsp_lib_"))
75 (minify-package "TXT2WEB.LIB" nil "qsp_lib_"))
76 (t
76 (t
77 (minify-package "TXT2WEB.MAIN" t "_")
77 (minify-package "TXT2WEB.MAIN" t "_")
78 (minify-package "TXT2WEB.API" t "a_")
78 (minify-package "TXT2WEB.API" t "a_")
79 (minify-package "TXT2WEB.LIB" t "l_")))
79 (minify-package "TXT2WEB.LIB" t "l_")))
80 (format nil "~{~A~^~%~%~}" (mapcar #'ps:ps* (reverse (js compiler))))))
80 (format nil "~{~A~^~%~%~}" (mapcar #'ps:ps* (reverse (js compiler))))))
81
81
82 ;;; CSS
82 ;;; CSS
83
83
84 (defmethod css-sources ((compiler compiler))
84 (defmethod css-sources ((compiler compiler))
85 (format nil "~{~A~^~%~%~}" (css compiler)))
85 (format nil "~{~A~^~%~%~}" (css compiler)))
86
86
87 ;;; HTML
87 ;;; HTML
88
88
89 (defmethod html-sources ((compiler compiler))
89 (defmethod html-sources ((compiler compiler))
90 (let ((flute:*escape-html* nil)
90 (let ((flute:*escape-html* nil)
91 (body-template (body compiler))
91 (body-template (body compiler))
92 (js (js-sources compiler))
92 (js (js-sources compiler))
93 (css (css-sources compiler)))
93 (css (css-sources compiler)))
94 (with-output-to-string (out)
94 (with-output-to-string (out)
95 (write
95 (write
96 (flute:h
96 (flute:h
97 (html
97 (html
98 (head
98 (head
99 (title "SugarQSP"))
99 (title "txt2web"))
100 (body
100 (body
101 body-template
101 body-template
102 (style css)
102 (style css)
103 (script js))))
103 (script js))))
104 :stream out
104 :stream out
105 :pretty nil))))
105 :pretty nil))))
106
106
107 (defun filename-game (filename)
107 (defun filename-game (filename)
108 (let ((filename (alexandria:lastcar (uiop:split-string filename :separator "/"))))
108 (let ((filename (alexandria:lastcar (uiop:split-string filename :separator "/"))))
109 (format nil "~{~A~^.~}" (butlast (uiop:split-string filename :separator ".")))))
109 (format nil "~{~A~^.~}" (butlast (uiop:split-string filename :separator ".")))))
110
110
111 (defmethod initialize-instance ((compiler compiler) &key sources ((:js js-files)) ((:css css-files)) ((:body body-file)) compile &allow-other-keys)
111 (defmethod initialize-instance ((compiler compiler) &key sources ((:js js-files)) ((:css css-files)) ((:body body-file)) compile &allow-other-keys)
112 (call-next-method)
112 (call-next-method)
113 (with-slots (body css js)
113 (with-slots (body css js)
114 compiler
114 compiler
115 ;; Compile the game's JS
115 ;; Compile the game's JS
116 (dolist (source sources)
116 (dolist (source sources)
117 (let ((ps (parse-file source))
117 (let ((ps (parse-file source))
118 (game-name (filename-game source)))
118 (game-name (filename-game source)))
119 (destructuring-bind (kw &rest locations)
119 (destructuring-bind (kw &rest locations)
120 ps
120 ps
121 (unless (eq kw 'lib:game)
121 (unless (eq kw 'lib:game)
122 (report-error "Internal error!"))
122 (report-error "Internal error!"))
123 (push
123 (push
124 `(lib:game (,game-name) ,@locations)
124 `(lib:game (,game-name) ,@locations)
125 js))))
125 js))))
126 ;; Does the user need us to do anything else
126 ;; Does the user need us to do anything else
127 (unless compile
127 (unless compile
128 ;; Read in body
128 ;; Read in body
129 (when body-file
129 (when body-file
130 (setf body
130 (setf body
131 (alexandria:read-file-into-string body-file)))
131 (alexandria:read-file-into-string body-file)))
132 ;; Include js files
132 ;; Include js files
133 (dolist (js-file js-files)
133 (dolist (js-file js-files)
134 (push (format nil "////// Included file ~A~%~A" js-file
134 (push (format nil "////// Included file ~A~%~A" js-file
135 (alexandria:read-file-into-string js-file))
135 (alexandria:read-file-into-string js-file))
136 js))
136 js))
137 ;; Include css files
137 ;; Include css files
138 (when css-files
138 (when css-files
139 ;; User option overrides the default css
139 ;; User option overrides the default css
140 (setf css nil)
140 (setf css nil)
141 (dolist (css-file css-files)
141 (dolist (css-file css-files)
142 (push (format nil "////// Included file ~A~%~A" css-file
142 (push (format nil "////// Included file ~A~%~A" css-file
143 (alexandria:read-file-into-string css-file))
143 (alexandria:read-file-into-string css-file))
144 css))))))
144 css))))))
145
145
146 (defmethod write-compiled-file ((compiler compiler))
146 (defmethod write-compiled-file ((compiler compiler))
147 (alexandria:write-string-into-file
147 (alexandria:write-string-into-file
148 (if (compile-only compiler)
148 (if (compile-only compiler)
149 ;; Just the JS
149 ;; Just the JS
150 (js-sources compiler)
150 (js-sources compiler)
151 ;; All of it
151 ;; All of it
152 (html-sources compiler))
152 (html-sources compiler))
153 (target compiler) :if-exists :supersede))
153 (target compiler) :if-exists :supersede))
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now