mirror of
https://gitlab.com/vindarel/ciel.git
synced 2026-01-07 09:42:31 -08:00
scripting: enable shebang line 🚀
This commit is contained in:
parent
2804f115d0
commit
baf2d2dd51
2 changed files with 93 additions and 4 deletions
|
|
@ -1,20 +1,77 @@
|
|||
|
||||
(in-package :ciel)
|
||||
|
||||
(defun maybe-ignore-shebang (in)
|
||||
"If this file starts with #!, delete the shebang line,
|
||||
so we can LOAD the file.
|
||||
Return: a stream (it is LOADable)."
|
||||
;; thanks Roswell for the trick.
|
||||
(let ((first-line (read-line in)))
|
||||
(make-concatenated-stream
|
||||
;; remove shebang:
|
||||
(make-string-input-stream
|
||||
(format nil "~a"
|
||||
(if (str:starts-with-p "#!" first-line)
|
||||
""
|
||||
first-line)))
|
||||
;; rest of the file:
|
||||
in)))
|
||||
|
||||
(defun load-without-shebang (file)
|
||||
"LOAD this file, but exclude the first line if it is a shebang line."
|
||||
(with-open-file (file-stream file)
|
||||
(load
|
||||
(maybe-ignore-shebang file-stream))))
|
||||
|
||||
(defun has-shebang (file)
|
||||
"Return T if the first line of this file is a shell shebang line (starts with #!)."
|
||||
(with-open-file (s file)
|
||||
(str:starts-with-p "#!" (read-line s))))
|
||||
|
||||
(defun main ()
|
||||
"Run a lisp file as a script.
|
||||
If no file is given or if it doesn't exist, run the top-level CIEL REPL.
|
||||
If no argument is given or if the file doesn't exist, run the top-level CIEL
|
||||
|
||||
It should begin with:
|
||||
The script should begin with:
|
||||
|
||||
(in-package :ciel-user)
|
||||
|
||||
We have two ways to run a CIEL script:
|
||||
|
||||
1) by calling the ciel binary with a file as argument:
|
||||
|
||||
$ ciel myscript.lisp
|
||||
|
||||
2) by using a shebang. It's a little bit convoluted:
|
||||
|
||||
#!/bin/sh
|
||||
#|-*- mode:lisp -*-|#
|
||||
#|
|
||||
exec /path/to/ciel `basename $0` \"$@\"
|
||||
(print \"hello CIEL!\")
|
||||
|
||||
How it works:
|
||||
|
||||
- it starts as a /bin/sh script
|
||||
- all lines starting by # are shell comments
|
||||
- the exec calls the ciel binary with this file name as first argument,
|
||||
the rest of the file (lisp code) is not read by the shell.
|
||||
- before LOAD-ing this Lisp file, we remove the #!/bin/sh shebang line.
|
||||
- Lisp ignore comments between #| and |#
|
||||
|
||||
Exciting things to come!"
|
||||
;; (format t "Hello main! ~S~&" uiop:*command-line-arguments*)
|
||||
(let ((file (first (uiop:command-line-arguments))))
|
||||
(cond
|
||||
((and file
|
||||
(uiop:file-exists-p file))
|
||||
(load file))
|
||||
(if (has-shebang file)
|
||||
;; I'm a bit cautious about this function.
|
||||
;; (mostly, small issues when testing at the REPL, should be fine though…)
|
||||
(load-without-shebang file)
|
||||
;; So the one with no risk:
|
||||
(load file)))
|
||||
(t
|
||||
(when (and file (not (uiop:file-exists-p file)))
|
||||
(format t "warn: file ~S does not exist.~&" file))
|
||||
(sbcli::repl)))))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue