changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > core / lisp/bin/skel.lisp

changeset 664: 4d8451fe5423
parent: cc89b337384b
child: 5f88b237ce29
author: Richard Westhaver <ellis@rwest.io>
date: Sun, 22 Sep 2024 01:02:49 -0400
permissions: -rw-r--r--
description: moved web to lib/web, added dat/css
1 ;;; Code:
2 
3 ;; TODO 2024-05-09: add shell configurables to rules - maybe at sk-command
4 ;; level. :INPUT :WAIT :OUTPUT
5 (in-package :std-user)
6 (defpkg :bin/skel
7  (:use :cl :std :cli
8  :vc :sb-ext :skel :log :cli/clap/util
9  :dat/sxp #+tools :skel/tools/viz)
10  (:import-from :cli/shell :*shell-input* :*shell-directory*)
11  (:use :cli/tools/sbcl))
12 
13 (in-package :bin/skel)
14 (in-readtable :shell)
15 
16 (defopt skc-help (print-help *cli*))
17 (defopt skc-version (print-version *cli*))
18 (defopt skc-level *log-level*
19  (setq *log-level* (if *arg* (if (stringp *arg*)
20  (sb-int:keywordicate (string-upcase *arg*))
21  *arg*)
22  :info)))
23 
24 (defopt skc-config (load-user-skelrc (or *arg* *user-skelrc*)))
25 
26 (defcmd skc-edit
27  (let ((file (or (when *args* (pop *args*)) (sk-path *skel-project*))))
28  (cli/ed:run-emacsclient (namestring file))))
29 
30 (defcmd skc-init
31  (let ((file (when *args* (pop *args*)))
32  (name (when (> *argc* 1) (pop *args*))))
33  ;; TODO: test, may need to be
34  ;; sequential for side-effect
35  ;; of pop
36  (handler-bind
37  ((sb-ext:file-exists
38  #'(lambda (s)
39  (std:println (format nil "file already exists: ~A" (or file *default-skelfile*)))
40  (let ((f2 (read-line)))
41  (if (string= f2 "")
42  (error s)
43  (use-value f2 s))))))
44  (init-skelfile file name))))
45 
46 (defcmd skc-describe
47  (describe
48  (if (> *argc* 0)
49  (find-skelfile (pathname (car *args*)) :load t)
50  (or *skel-project* *skel-user-config* *skel-system-config*))))
51 
52 
53 (defcmd skc-inspect
54  (sb-ext:enable-debugger)
55  (setq *no-exit* t)
56  (inspect
57  (find-skelfile
58  (if *args* (pathname (car *args*))
59  #P".")
60  :load t)))
61 
62 #+gui
63 (defcmd skc-view
64  (if *args*
65  (let ((stuff (loop for a in *args*
66  collect (sk-slot-case a))))
67  (sk-view (if (= 1 (length stuff)) (car stuff) stuff)))
68  (sk-view (if (boundp '*skel-project*) *skel-project*
69  (if (boundp '*skel-user-config*) *skel-user-config*
70  (if (boundp '*skel-system-config*) *skel-system-config*
71  (skel-simple-error "skel config files not installed")))))))
72 
73 (defcmd skc-id
74  (println (std:format-sxhash (obj/id:id (find-skelfile #P"." :load t)))))
75 
76 (defun call-with-args (action args)
77  (let* ((*default-pathname-defaults* *skel-path*))
78  (if (null args)
79  (sk-call *skel-project* action)
80  (mapc (lambda (x)
81  (sk-call *skel-project* (keywordicate (symbol-name action) '- (string-upcase x))))
82  args))))
83 
84 (defcmd skc-compile
85  (call-with-args :compile *args*))
86 (defcmd skc-build
87  (call-with-args :build *args*))
88 (defcmd skc-dist
89  (call-with-args :dist *args*))
90 (defcmd skc-install
91  (call-with-args :install *args*))
92 (defcmd skc-pack
93  (call-with-args :pack *args*))
94 (defcmd skc-unpack
95  (call-with-args :unpack *args*))
96 (defcmd skc-bundle
97  (call-with-args :bundle *args*))
98 (defcmd skc-unbundle
99  (call-with-args :unbundle *args*))
100 (defcmd skc-clean
101  (call-with-args :clean *args*))
102 (defcmd skc-test
103  (call-with-args :test *args*))
104 (defcmd skc-bench
105  (call-with-args :bench *args*))
106 (defcmd skc-save
107  (call-with-args :save *args*))
108 
109 (defun sk-slot-case (sel)
110  (std/string:string-case ((string-left-trim ":" sel) :default (skel-simple-error "invalid slot"))
111  ("id" (std:format-sxhash (obj/id:id *skel-project*)))
112  ("name" (sk-name *skel-project*))
113  ("author" (sk-author *skel-project*))
114  ("version" (sk-version *skel-project*))
115  ("description" (sk-description *skel-project*))
116  ("tags" (sk-tags *skel-project*))
117  ("license" (sk-license *skel-project*))
118  ("vc" (sk-vc *skel-project*))
119  ("components" (sk-components *skel-project*))
120  ("scripts" (sk-scripts *skel-project*))
121  ("rules" (sk-rules *skel-project*))
122  ("phases" (hash-table-alist (sk-phases *skel-project*)))
123  ;; ("env" (sk-env *skel-project*))
124  ("bind" (sk-bind *skel-project*))
125  ("include" (sk-include *skel-project*))
126  ("stash" (sk-stash *skel-project*))
127  ("store" (sk-store *skel-project*))
128  ("config" *skel-user-config*)
129  ("sys" *skel-system-config*)
130  ("cache" (sk-cache *skel-user-config*))))
131 
132 (defcmd skc-show
133  (if *args*
134  (mapc (lambda (x) (when-let ((ret (sk-slot-case x))) (println ret))) *args*)
135  (sk-print (if (boundp '*skel-project*) *skel-project*
136  (if (boundp '*skel-user-config*) *skel-user-config*
137  (if (boundp '*skel-system-config*) *skel-system-config*
138  (skel-simple-error "skel config files not installed")))))))
139 
140 (defcmd skc-push
141  (case (sk-vc-meta-kind (sk-vc (find-skelfile #P"." :load t)))
142  (:git (run-git-command "push" *args* t))
143  (:hg (run-hg-command "push" *args* t))
144  (t (skel-simple-error "unknown VC type"))))
145 
146 (defcmd skc-pull
147  (case (sk-vc-meta-kind (sk-vc (find-skelfile #P"." :load t)))
148  (:git (run-git-command "pull" *args* t))
149  (:hg (run-hg-command "pull" (append '("-u") *args*) t))
150  (t (skel-simple-error "unknown VC type"))))
151 
152 (defun hg-status ()
153  (with-open-stream (proc (process-output (run-hg-command "status" nil :stream)))
154  (loop for x = (read-line proc nil)
155  while x
156  do (println x))))
157 
158 (defun git-status ()
159  (with-open-stream (proc (run-git-command "status" nil :stream))
160  (loop for x = (read-line proc nil)
161  while x
162  do (println x))))
163 
164 (defcmd skc-status
165  (case (sk-vc-meta-kind (sk-vc (find-skelfile #P"." :load t)))
166  (:git (git-status))
167  (:hg (hg-status))
168  (t (hg-status))))
169 
170 (defcmd skc-clone
171  (case (sk-vc-meta-kind (sk-vc (find-skelfile #P"." :load t)))
172  (:git (run-git-command "clone" *args* t))
173  (:hg (run-hg-command "clone" *args* t))
174  (t (skel-simple-error "unknown VC type"))))
175 
176 (defcmd skc-commit
177  (case (sk-vc-meta-kind (sk-vc (find-skelfile #P"." :load t)))
178  (:git (run-git-command "commit" (append '("-m") *args*) t))
179  (:hg (run-hg-command "commit" (when *args* (append '("-m") *args*)) t))
180  (t (skel-simple-error "unknown VC type"))))
181 
182 (defcmd skc-make
183  (let ((sk (find-skelfile #P"." :load t)))
184  (sb-ext:enable-debugger)
185  (log:debug! "cli args" *args*)
186  ;; (setq *no-exit* t)
187  (if *args*
188  (loop for a in *args*
189  do (debug!
190  (if-let ((rule (sk-find-rule a sk)))
191  (sk-make sk rule)
192  ;; TODO 2024-08-23: restart condition here
193  (skel-simple-error "rule not found: ~A" a))))
194  (debug! (sk-make sk (aref (sk-rules sk) 0))))))
195 
196 (defcmd skc-run
197  (if *args*
198  (mapc (lambda (script)
199  ;; first check if a script with the same name exists, else check for a rule definition
200  (if-let ((script (sk-find-script
201  (pathname-name script)
202  (find-skelfile #P"." :load t))))
203  (sk-run script)
204  (call-with-args :run (list script))))
205  *args*)
206  (required-argument 'name)))
207 
208 (defcmd skc-vc
209  (let* ((sk (find-skelfile #P"." :load t))
210  (vc (sk-vc-meta-kind (sk-vc sk))))
211  (sb-ext:enable-debugger)
212  (with-open-stream (proc (process-output
213  (if-let ((cmd (pop *args*)))
214  (ecase vc
215  (:hg (run-hg-command cmd *args* :stream))
216  (:git (run-git-command cmd *args* :stream)))
217  (sb-ext:run-program (case vc (:hg *hg-program*) (:git *git-program*))
218  nil
219  :output :stream))))
220  (loop for x = (read-line proc nil)
221  while x
222  do (println x)))))
223 
224 (defcmd skc-shell
225  (sb-ext:enable-debugger)
226  (trace! "starting skel shell")
227  (setq *no-exit* t)
228  (cli/clap::with-cli-handlers
229  (progn
230  (in-package :sk-user)
231  (use-package :cl-user)
232  (use-package :sb-ext)
233  (use-package :std-user)
234  (init-skel-vars)
235  (println "Welcome to SKEL")
236  (sb-impl::toplevel-repl nil))))
237 
238 (defcmd skc-new
239  (println *args*)
240  (println *opts*))
241 
242 (define-cli *skel-cli*
243  :name "skel"
244  :version #.(format nil "0.1.1:~A" (read-line (sb-ext:process-output (vc:run-hg-command "id" '("-i") :stream))))
245  :description "A hacker's project compiler."
246  :thunk 'skc-show
247  :opts ((:name "help" :global t :description "print this message"
248  :thunk skc-help)
249  (:name "version" :global t :description "print version"
250  :thunk skc-version)
251  (:name "level" :global t :description "set log level (warn,info,debug,trace)"
252  :thunk skc-level)
253  (:name "config" :global t :description "set a custom skel user config" :kind file)
254  (:name "input" :global t :description "input source" :kind string)
255  (:name "output" :global t :description "output target" :kind string))
256  :cmds ((:name init
257  :description "initialize a skelfile in the current directory"
258  :opts (:name "name" :description "project name" :kind string)
259  :thunk skc-init)
260  (:name new
261  :description "make a new skel project"
262  :opts ((:name "name" :description "project name" :kind string))
263  :thunk skc-new)
264  (:name describe
265  :description "describe a skelfile"
266  :thunk skc-describe)
267  (:name show
268  :description "show project slots"
269  :opts ((:name "file" :description "path to skelfile" :kind file))
270  :thunk skc-show)
271  (:name vc
272  :description "version control"
273  :thunk skc-vc
274  :opts ((:name "root" :description "repository path" :kind directory)))
275  (:name id
276  :description "print the project id"
277  :thunk skc-id)
278  (:name inspect
279  :description "inspect the project skelfile"
280  :opts ((:name "file" :description "path to skelfile" :kind file))
281  :thunk skc-inspect)
282  #+tools
283  (:name view
284  :description "view an object in a new GUI window"
285  :thunk skc-view)
286  (:name make
287  :description "build project targets"
288  :opts ((:name "target" :description "target to build" :kind string))
289  :thunk skc-make)
290  (:name run
291  :description "run a script or command"
292  :thunk skc-run)
293  (:name compile
294  :description "compile source code"
295  :thunk skc-compile)
296  (:name build
297  :description "build programs and libraries"
298  :thunk skc-build)
299  (:name save
300  :description "save a file"
301  :thunk skc-save)
302  (:name dist
303  :description "distribute build artifacts"
304  :thunk skc-dist)
305  (:name install
306  :description "install stuff"
307  :thunk skc-install)
308  (:name pack
309  :description "pack stuff"
310  :thunk skc-pack)
311  (:name unpack
312  :description "unpack stuff"
313  :thunk skc-unpack)
314  (:name bundle
315  :description "bundle source code"
316  :thunk skc-bundle)
317  (:name unbundle
318  :description "unbundle source code"
319  :thunk skc-unbundle)
320  (:name clean
321  :description "clean up the project"
322  :thunk skc-clean)
323  (:name test
324  :description "run tests"
325  :thunk skc-test)
326  (:name bench
327  :description "run benchmark"
328  :thunk skc-bench)
329  (:name status
330  :description "print the vc status"
331  :thunk skc-status)
332  (:name push
333  :description "push the current project upstream"
334  :thunk skc-push)
335  (:name pull
336  :description "pull the current project from remote"
337  :thunk skc-pull)
338  (:name clone
339  :description "clone a remote project"
340  :thunk skc-clone)
341  (:name commit
342  :description "commit changes to the project vc"
343  :thunk skc-commit
344  :opts ((:name "message" :description "commit message" :kind string)))
345  (:name edit
346  :description "edit a project file in emacs."
347  :thunk skc-edit)
348  (:name shell
349  :description "open the sk-shell interpreter"
350  :thunk skc-shell)))
351 
352 (defmain start-skel ()
353  (in-package :sk-user)
354  (let ((*log-level* :info))
355  (in-readtable :shell)
356  (with-cli (*skel-cli* opts cmds) (cli:args)
357  (init-skel-vars)
358  (when-let ((project (find-skelfile #P".")))
359  (let ((*default-pathname-defaults* (pathname (directory-namestring project))))
360  (setq *skel-project* (load-skelfile project))
361  (setq *skel-path* (sk-src *skel-project*))
362  (setq cli/shell:*shell-directory* (sk-src *skel-project*))))
363  (do-cmd *cli*)
364  (debug-opts *cli*))))