(in-package :ciel) (defparameter *ciel-version* #.(asdf:component-version (asdf:find-system :ciel)) "CIEL's version, read from the .asd.") (defparameter *scripts* (dict 'equalp) "Available scripts. Hash-table: file name (sans extension) -> file content (string). The name is case-insensitive (it's easier for typing things in the terminal).") ;; eval (defun wrap-user-code (s) "Wrap this user code to handle common conditions, such as a C-c C-c to quit gracefully." ;; But is it enough when we run a shell command? `(handler-case ,s ;; --eval takes one form only so no need of ,@ (sb-sys:interactive-interrupt (c) (declare (ignore c)) (format! *error-output* "Bye!~%")) (error (c) (format! *error-output* "~a" c)))) (defun register-builtin-scripts () "Find available scripts in src/scripts, register them in *SCRIPTS*. Call this before creating the CIEL binary." ;; We save the file's content as a string. ;; We will run them with LOAD (and an input stream from the string). ;; ;; Example: ;; ;; (load (make-string-input-stream (str:from-file "src/scripts/simpleHTTPserver.lisp"))) (loop for file in (uiop:directory-files "src/scripts/") if (equal "lisp" (pathname-type file)) do (format t "~t scripts: registering ~a~&" (pathname-name file)) (setf (gethash (pathname-name file) *scripts*) (str:from-file file)))) (defun run-script (name) "If NAME is registered in *SCRIPTS*, run this script." (bind (((:values content exists) (gethash name *scripts*))) (cond ((and exists (str:blankp content) (format *error-output* "uh the script ~s has no content?~&" name))) ((not exists) (format *error-output* "The script ~s was not found.~&" name)) (t ;; Run it! ;; We first add a symbol in the feature list, so a script nows when it is being executed. (push :ciel ciel-user::*features*) ;; We ignore the shebang line, if there is one. ;; We can call scripts either with ciel -s or with ./script (load (maybe-ignore-shebang (make-string-input-stream content))))))) (defun top-level/command () "Creates and returns the top-level command" (clingon:make-command :name "ciel" :description "CIEL Is an Extended Lisp. It's Common Lisp, batteries included." :version *ciel-version* :license "todo" :authors '("vindarel ") :usage (format nil "accepts optional command-line arguments.~% ~t~tWith no arguments, run the CIEL readline REPL.~% ~t~tWith a file as argument, run it as a script.~% ~t~tWith --eval / -e
, eval a Lisp form.~% ~t~tWith --script / -s