changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > core / lisp/bin/skel.lisp

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