changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > core / lisp/bin/skel.lisp

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