4
|
1
|
* Mock Skel Readme |
9
|
2
|
:PROPERTIES: |
|
3
|
:ID: a072a011-0808-490b-b4ee-c665f68e4033 |
|
4
|
:END: |
4
|
5
|
** Overview |
9
|
6
|
:PROPERTIES: |
|
7
|
:ID: 2ab70bb9-4f1e-4ba2-ad72-b2a32dacbd5b |
|
8
|
:END: |
1
|
9
|
+ status :: WIP |
|
10
|
+ forge :: [[https://lab.rwest.io/ellis/skel][Heptapod]] |
|
11
|
+ mirror :: [[https://github.com/richardwesthaver/skel][Github]] |
|
12
|
|
|
13
|
This system provides functions and macros for building and deploying |
|
14
|
project skeletons. /This is not a general purpose templating |
|
15
|
system/. It is specifically for my software stack. |
|
16
|
|
4
|
17
|
*** Goals |
9
|
18
|
:PROPERTIES: |
|
19
|
:ID: 7881a92f-7406-4862-bf89-39970731f37d |
|
20
|
:END: |
1
|
21
|
- vaporize boilerplate code and docs |
|
22
|
- integrate reasonably well with my tools (Emacs/etc) |
|
23
|
- object-oriented project management |
4
|
24
|
*** Resources |
9
|
25
|
:PROPERTIES: |
|
26
|
:ID: d0dd3e94-8c9e-4eac-847e-33a039beadbe |
|
27
|
:END: |
1
|
28
|
- [[https://www.gnu.org/software/emacs/manual/html_node/autotype/Skeleton-Language.html][skeleton-lanaguage (emacs)]] |
|
29
|
- [[https://github.com/emacs-mirror/emacs/tree/master/lisp/cedet/ede][cedet/ede (emacs)]] |
|
30
|
- [[https://www.gnu.org/software/make/manual/make.html][GNU make]] |
|
31
|
- [[https://docs.factorcode.org/content/article-vocabularies.html][Factor (forth) definitions]] |
4
|
32
|
** Quickstart |
9
|
33
|
:PROPERTIES: |
|
34
|
:ID: 183bbf4c-bb3c-44f6-a4c1-49c548e0eab2 |
|
35
|
:END: |
1
|
36
|
Make sure you have sbcl installed: |
2
|
37
|
#+begin_src shell :results pp :eval never |
1
|
38
|
sbcl --version |
|
39
|
#+end_src |
|
40
|
|
|
41
|
#+RESULTS: |
|
42
|
: SBCL 2.3.12+main |
|
43
|
|
|
44
|
Then compile the program. This command produces a binary called =skel= |
|
45
|
in the project root: |
|
46
|
#+begin_src shell :results raw silent |
|
47
|
sbcl --noinform --non-interactive --eval '(ql:quickload :app/cli/skel)' --eval '(asdf:make :app/cli/skel)' |
|
48
|
#+end_src |
|
49
|
|
|
50
|
Run the binary without any args, which will print a skeleton of the |
|
51
|
current project directory (=*skel-project*=). |
|
52
|
|
2
|
53
|
#+begin_src shell :results output replace :eval never |
1
|
54
|
skel -h |
|
55
|
#+end_src |
|
56
|
|
|
57
|
#+RESULTS: |
|
58
|
#+begin_example |
|
59
|
skel v0.1.1 |
|
60
|
usage: skel [global] <command> [<arg>] |
|
61
|
|
|
62
|
A hacker's project compiler and build tool. |
|
63
|
options: |
|
64
|
-h/--help* : print this message |
|
65
|
-v/--version* : print version |
|
66
|
-d/--debug* : set log level (debug,info,trace,warn) |
|
67
|
-c/--config* : set a custom skel user config |
|
68
|
-i/--input : input source |
|
69
|
-o/--output : output target |
|
70
|
commands: |
|
71
|
init : initialize a skelfile in the current directory |
|
72
|
-n/--name : project name |
|
73
|
|
|
74
|
show : describe the project skelfile |
|
75
|
-f/--file : path to skelfile |
|
76
|
|
|
77
|
inspect : inspect the project skelfile |
|
78
|
-f/--file : path to skelfile |
|
79
|
|
|
80
|
make : build project targets |
|
81
|
-t/--target : target to build |
|
82
|
|
|
83
|
run : run a script or command |
|
84
|
|
|
85
|
push : push the current project upstream |
|
86
|
|
|
87
|
pull : pull the current project from remote |
|
88
|
|
|
89
|
clone : clone a remote project |
|
90
|
|
|
91
|
commit : commit changes to the project vc |
|
92
|
|
|
93
|
edit : edit a project file |
|
94
|
|
|
95
|
shell : open the sk-shell interpreter |
|
96
|
|
|
97
|
#+end_example |
|
98
|
|
|
99
|
Here's skel's skelfile: |
|
100
|
|
|
101
|
#+begin_src shell :results output replace :wrap src skel :exports results |
|
102
|
cat skel.sk |
|
103
|
#+end_src |
|
104
|
|
|
105
|
#+RESULTS: |
|
106
|
#+begin_src skel |
|
107
|
;;; skelfile @ 2023-10-08.02:37:25 -*- mode: skel; -*- |
|
108
|
:name skel |
|
109
|
:author "ellis" |
|
110
|
:version "0.1.0" |
|
111
|
:description "a hacker's project compiler" |
|
112
|
:license "MPL" |
|
113
|
:vc :hg |
|
114
|
:tags ("lisp") |
|
115
|
:rules ((build () (print (asdf:make :skel/cli))) |
|
116
|
(clean () #$rm -rf */*.fasl$#)) |
|
117
|
:documents ((:org "readme")) |
|
118
|
:components |
|
119
|
((:elisp "sk") |
|
120
|
(:lisp-system |
|
121
|
"skel" |
|
122
|
:version "0.1.0" |
|
123
|
:maintainer "ellis <ellis@rwest.io>" |
|
124
|
:bug-tracker "https://lab.rwest.io/ellis/skel/issues" |
|
125
|
:class :package-inferred-system |
|
126
|
:defsystem-depends-on (:asdf-package-system) |
|
127
|
:depends-on (:uiop :asdf :sb-posix :sb-bsd-sockets :sb-concurrency :cl-ppcre :std :organ :skel/pkg) |
|
128
|
:in-order-to ((test-op (test-op skel/tests))) |
|
129
|
:perform (test-op (op c) (uiop:symbol-call '#:rt '#:do-tests)))) |
|
130
|
:stash "~/dev/comp/stash" |
|
131
|
:shed "~/dev/comp/shed" |
|
132
|
:abbrevs nil |
|
133
|
:snippets |
|
134
|
((autogen #$sbcl --eval '(ql:quickload :app/cli/skel)' --eval '(asdf:make :app/cli/skel)'$#)) |
|
135
|
#+end_src |
|
136
|
|
|
137
|
This is just a form without the top-level parentheses - you're free to |
|
138
|
omit them in a skelfile. |
|
139
|
|
4
|
140
|
*** describe |
9
|
141
|
:PROPERTIES: |
|
142
|
:ID: 9ae1fe7b-c373-4101-88d3-439793eb38f3 |
|
143
|
:END: |
1
|
144
|
The =describe= command can be used to check the currently active |
|
145
|
skelfile, printing any errors and the parsed object. |
|
146
|
|
2
|
147
|
#+begin_src shell :results output replace :eval never |
1
|
148
|
skel show |
|
149
|
#+end_src |
|
150
|
|
|
151
|
#+RESULTS: |
|
152
|
#+begin_example |
|
153
|
#<SKEL:SK-PROJECT :ID 1e61-38b1-c5fe-7eac> |
|
154
|
[standard-object] |
|
155
|
|
|
156
|
Slots with :INSTANCE allocation: |
|
157
|
NAME = SKEL |
|
158
|
PATH = #P"/home/ellis/dev/skel/skelfile" |
|
159
|
AUTHOR = "ellis" |
|
160
|
VERSION = "0.1.0" |
|
161
|
TAGS = ("lisp") |
|
162
|
DESCRIPTION = "a hacker's project compiler" |
|
163
|
LICENSE = "MPL" |
|
164
|
AST = NIL |
|
165
|
ID = 2189093230060928684 |
|
166
|
VC = :HG |
|
167
|
RULES = ((BUILD NIL (PRINT (ASDF/OPERATE:MAKE :SKEL/CLI))).. |
|
168
|
DOCUMENTS = ((:ORG "readme")) |
|
169
|
COMPONENTS = ((:ELISP "sk").. |
|
170
|
SCRIPTS = NIL |
|
171
|
SNIPPETS = ((AUTOGEN "sbcl --eval '(asdf:make :skel/cli)'")) |
|
172
|
STASH = #P"~/stash" |
|
173
|
SHED = #P"~/shed" |
|
174
|
ABBREVS = NIL |
|
175
|
IMPORTS = NIL |
|
176
|
#+end_example |
|
177
|
|
4
|
178
|
*** TODO compile |
9
|
179
|
:PROPERTIES: |
|
180
|
:ID: e43b7a81-c2f9-4dc9-8a09-66259602f91b |
|
181
|
:END: |
1
|
182
|
Skelfiles can be compiled to produce a new project skeleton or update |
|
183
|
an existing one. |
|
184
|
|
|
185
|
Try compiling skel's skelfile: |
|
186
|
|
|
187
|
#+begin_src shell :results output replace :exports code |
|
188
|
skel compile |
|
189
|
#+end_src |
|
190
|
|
|
191
|
You may also compile individual components of the project structure, |
|
192
|
for example, to compile the rules into a makefile: |
|
193
|
|
|
194
|
#+begin_src shell :results output replace :exports code |
|
195
|
skel compile --rules |
|
196
|
#+end_src |
|
197
|
|
2
|
198
|
#+begin_src shell :results output :wrap src makefile :eval never |
1
|
199
|
cat makefile |
|
200
|
#+end_src |
|
201
|
|
|
202
|
#+RESULTS: |
|
203
|
#+begin_src makefile |
|
204
|
### SKEL @ 2023-09-14.01:47:59 --- A hacker's project compiler -*- mode:makefile ; -*- |
|
205
|
LISP=sbcl --noinform --non-interactive --eval "(asdf:load-asd \"skel.asd\")" --eval "(ql:quickload :skel)" |
|
206
|
.PHONY: compile clean |
|
207
|
compile:;$(LISP) --eval "(asdf:compile-system :skel)" |
|
208
|
test:compile;$(LISP) --eval "(ql:quickload :skel/tests)" --eval "(in-package :skel.tests)" --eval "(compile-file \"tests.lisp\")" --eval "(load-file \"tests.lisp\")" --eval "(do-tests :skel)" |
|
209
|
clean:;rm -rf *.fasl |
|
210
|
debug:compile;$(LISP) --eval "(start-repl)" |
|
211
|
#+end_src |
|
212
|
|
4
|
213
|
** Examples |
9
|
214
|
:PROPERTIES: |
|
215
|
:ID: 61959899-98ec-4ee2-a862-7544674ffc7a |
|
216
|
:END: |
4
|
217
|
*** Default |
9
|
218
|
:PROPERTIES: |
|
219
|
:ID: b9e5324c-059d-4416-a19a-3e5ffbac554e |
|
220
|
:END: |
1
|
221
|
When you run =skel init= this is the basic skelfile that will be |
|
222
|
generated in the current directory, depending on the following |
|
223
|
contexts: |
|
224
|
- default user config |
|
225
|
- directory contents |
|
226
|
- cli args |
|
227
|
With no cli args or user config and an empty directory the output |
|
228
|
looks like this: |
|
229
|
#+begin_src skel |
|
230
|
;;; examples @ 2023-10-09.23:38:23 -*- mode: skel; -*- |
|
231
|
:name "examples" |
|
232
|
#+end_src |
4
|
233
|
*** Imports |
9
|
234
|
:PROPERTIES: |
|
235
|
:ID: c7e2d0d9-8b0e-428d-aeb5-1b1447e2a1ed |
|
236
|
:END: |
4
|
237
|
*** Multi |
9
|
238
|
:PROPERTIES: |
|
239
|
:ID: d6b6bbff-7713-4f2c-9dc8-b8331497b5b4 |
|
240
|
:END: |
4
|
241
|
** Tests |
9
|
242
|
:PROPERTIES: |
|
243
|
:ID: 37821915-2584-4303-a929-3cf25727fa1b |
|
244
|
:END: |
1
|
245
|
The unit tests may also be a useful reference: |
|
246
|
|
2
|
247
|
#+begin_src lisp :results output replace :wrap src lisp :eval never :package :skel.tests |
1
|
248
|
(ql:quickload :skel/tests) |
|
249
|
(in-package :skel.tests) |
|
250
|
(setq *log-level* nil) |
|
251
|
;; (setq *catch-test-errors* nil) |
|
252
|
(setq *compile-tests* t) |
|
253
|
(list (multiple-value-list (do-tests :skel)) (test-results *test-suite*)) |
|
254
|
#+end_src |
|
255
|
|
|
256
|
#+RESULTS: |
|
257
|
#+begin_src lisp |
|
258
|
To load "skel/tests": |
|
259
|
Load 1 ASDF system: |
|
260
|
skel/tests |
|
261
|
; Loading "skel/tests" |
|
262
|
.................................................. |
|
263
|
[package skel.vc]................................. |
|
264
|
[package skel.virt]............................... |
|
265
|
[package skel.comp.asd]........................... |
|
266
|
[package skel.make]............................... |
|
267
|
[package skel.ext.asdf]........................... |
|
268
|
[package skel.tests]. |
|
269
|
in suite SKEL with 6/6 tests: |
|
270
|
#<PASS VM-TEST788> |
|
271
|
#<PASS MAKEFILE-TEST787> |
|
272
|
#<PASS SKELRC-TEST786> |
|
273
|
#<PASS SKELFILE-TEST785> |
|
274
|
#<PASS HEADER-COMMENTS-TEST784> |
|
275
|
#<PASS SANITY-TEST783> |
|
276
|
No tests failed. |
|
277
|
#+end_src |
|
278
|
|
4
|
279
|
** API |
9
|
280
|
:PROPERTIES: |
|
281
|
:ID: ae46b723-6d1e-4855-9ec1-ad0eb7093960 |
|
282
|
:END: |
1
|
283
|
- TODO :: CLOS-based core classes |
|
284
|
- TODO :: EIEIO-based wrapper classes |
|
285
|
|
15
|
286
|
#+begin_src dot :file /tmp/api.svg :exports results |
1
|
287
|
digraph { splines=true; label="CLOS API"; labelloc="t"; node [shape=record]; |
|
288
|
sk [label="(skel :ID :AST)"] |
|
289
|
methods [label="(sk-compile sk-expand sk-build\nsk-run sk-init sk-new sk-save\nsk-tangle sk-weave sk-call sk-print)"] |
|
290
|
skmet [label="(sk-meta :NAME :PATH :VERSION :DESCRIPTION)"] |
|
291
|
skvcs [label="(sk-vc-meta :VC)"] |
|
292
|
skcmd [label="(sk-command)"] |
|
293
|
sktar [label="(sk-target)"] |
|
294
|
sksrc [label="(sk-source)"] |
|
295
|
skrec [label="(sk-recipe :COMMANDS)"] |
|
296
|
skrul [label="(sk-rule :TARGET :SOURCE :RECIPE)"] |
|
297
|
skdoc [label="(sk-document)"] |
|
298
|
skscr [label="(sk-script)"] |
|
299
|
skcfg [label="(sk-config)"] |
|
300
|
sksni [label="(sk-snippet)"] |
|
301
|
skabb [label="(sk-abbrev)"] |
|
302
|
skpro [label="(sk-project\l:RULES\l:DOCUMENTS\l:SCRIPTS\l:SNIPPETS\l:ABBREVS)\l"] |
|
303
|
sk -> skmet |
|
304
|
skmet -> skvcs |
|
305
|
sk -> skcfg |
|
306
|
sk -> sksni |
|
307
|
sk -> skabb |
|
308
|
sk -> sktar |
|
309
|
sk -> skrul |
|
310
|
sk -> sksrc |
|
311
|
sk -> skcmd |
|
312
|
skvcs -> skpro |
|
313
|
skmet -> skdoc |
|
314
|
skmet -> skscr |
|
315
|
skrul -> skpro |
|
316
|
skscr -> skpro |
|
317
|
skdoc -> skpro |
|
318
|
sksni -> skpro |
|
319
|
skabb -> skpro |
|
320
|
sktar -> skrul |
|
321
|
sksrc -> skrul |
|
322
|
skrec -> skrul |
|
323
|
skcmd -> skrec |
|
324
|
} |
|
325
|
#+end_src |
|
326
|
|
|
327
|
#+RESULTS: |
15
|
328
|
[[file:/tmp/api.svg]] |