I've been playing with my dotfiles again... in particular the ones for getting SBCL (the Lisp compiler of choice) up and running with various package managers and settings.
Obviously the *first* thing to do is to get it so that everything is debugable by default... having to go and up the optimization level manually is a drag and computers are fast:
(sb-ext:restrict-compiler-policy 'debug 3)
Oh and SBCL has a better prompt (well... a more Slime-y one) so we can turn that on too:
(ignore-errors (require 'sb-aclrepl)) (when (find-package 'sb-acl-repl) (push :aclrepl cl:*features*))
And then there's Quicklisp: the defacto package manager for most Lisp people. Normally you go and install it manually and add a couple of lines to your `.sbclrc` to load it... but lets automate that so it gets installed on first run instead!
A couple of macros to run programs (without resorting to libraries):
(defun run-program-with-exit-code (program &rest args) "Run the PROGRAM with ARGS, wait for it to finish then return its exit code." (let ((p (sb-ext:run-program program args :search t))) (sb-ext:process-wait p) (sb-ext:process-exit-code p))) (defun run-programs-successfully (&rest script) "Run each program in the SCRIPT stopping if any return an exit code." (every (lambda (line) (zerop (apply #'run-program-with-exit-code line))) script))
Then if Quicklisp isn't already available download and install it... else load it.
#-quicklisp (let* ((quicklisp-dir (merge-pathnames ".local/share/sbcl/quicklisp/" (user-homedir-pathname))) (quicklisp-init (merge-pathnames "setup.lisp" quicklisp-dir))) (unless (probe-file quicklisp-init) (format t "~&;; attempting to download quicklisp~%") (if (run-programs-successfully '("curl" "-O" "https://beta.quicklisp.org/quicklisp.lisp") '("curl" "-O" "https://beta.quicklisp.org/quicklisp.lisp.asc") '("curl" "-O" "https://beta.quicklisp.org/release-key.txt") '("gpg" "--import" "release-key.txt") '("gpg" "--verify" "quicklisp.lisp.asc" "quicklisp.lisp")) (if (probe-file #P"quicklisp.lisp") (progn (format t "~&;; attempting to install quicklisp~%") (if (run-programs-successfully '("sbcl" "--non-interactive" "--eval" (format nil "(quicklisp-quickstart:install :path \"~S\")" quicklisp-dir))) (progn (format t "~&;; quicklisp installed: restart sbcl~%") (sb-ext:exit :abort t)) (warn "failed to install quicklisp. Try installing manually"))) (progn (warn "failed to download quicklisp: you should attempt to install it manually. See https://quicklisp.org/beta/"))) (warn "Couldn't detect quicklisp and couldn't install it: you should attempt to install manually. See: https://quicklisp.org/beta/"))) (when (probe-file quicklisp-init) (load quicklisp-init)))
I couldn't quite get SBCL to run and load the `quicklisp.lisp` installer itself (it'd complain about the `quicklisp-quickstart` package being missing) so I instead re-run SBCL and crash out this time. Sure it could be better but its quite neat and saves a job every time I change OS! Neat-o!