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!