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