Setting up sketch
Table of Contents
The problem
I recently wanted to try out Sketch, a creative coding environment for Common Lisp. I am using one of the Fedora Atomic Desktops and wanted to set things up in such a way that I could start Emacs on the host and have the Common Lisp interpreter running inside a toolbox container.
Setting up the container
First, I created a new container and entered it with
toolbox create lisp toolbox enter
Dependencies
I chose SBCL as the Common Lisp implementation but according to the Sketch documentation CCL should also work. Sketch needs SDL2 for rendering and OpenGL drivers available inside the container. After some trial and error I ended up with the following two commands that seemed to install all required dependencies (again, in the container):
sudo dnf update sudo dnf install \ glx-utils \ mesa-libGLU \ mesa-libGL \ sdl2-compat \ SDL2_ttf \ SDL2_image \ sbcl \ libffi \ libffi-devel \ gcc \ redhat-rpm-config
Quicklisp
The Sketch readme recommends to install the program via Quicklisp, a package manager for Common Lisp. Inside the container, we can install it with
curl -o quicklisp.lisp https://beta.quicklisp.org/quicklisp.lisp sbcl --load quicklisp.lisp
The second command should open the SBCL interpreter where we enter the following two lines:
(quicklisp-quickstart:install) (ql:add-to-init-file)
Setting up the host Emacs
Installing Slime
Inside Emacs running on the host (i.e. not inside the container), I first installed SLIME. Then, following the SLIME documentation, I set the Lisp program to the SBCL inside the container:
(setq inferior-lisp-program "toolbox run -c lisp sbcl")
Running a sketch
With that everything should be set up!
Save the following block in file and save it as tutorial.lisp.
(ql:quickload :sketch) (defpackage :tutorial (:use :cl :sketch)) (in-package :tutorial) (defun sawtooth (x) (if (< x 1.0) x (- 2.0 x))) (defsketch tutorial ((title "tutorial") (width 600) (height 600) (frame 0) (time 0) (fr 60) (circles (make-array `(10 2) :initial-element 0)) (cx (/ width 2)) (cy (/ height 2)) (cc (random-color))) (let* ((nr (* fr 5)) (ng (* fr 8)) (nb (* fr 2)) (r (sawtooth (/ (mod frame (* 2 nr)) nr))) (g (sawtooth (/ (mod frame (* 2 ng)) ng))) (b (sawtooth (/ (mod frame (* 2 nb)) nb)))) (background (rgb r g b))) (if (eq 0 (mod frame fr)) (setf cx (random width) cy (random height) cc (random-color))) (with-pen (make-pen :stroke +black+ :fill cc :weight 4) (circle cx cy (* (/ width 6) (sawtooth (/ (mod frame fr) fr))))) (incf frame) (setf time (/ 1.0 frame))) (make-instance 'tutorial)
Start SLIME with M-x slime and evaluate the buffer with M-x slime-eval-buffer.
Here is a short video:
Conclusion
There is nothing very special about the setup, but it took me longer than I had expected, so I thought I would write it down. Now I just have to make some sketches :)