changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > core / lisp/bin/skel.lisp

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