[index] [pictures] [about] [how]

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 :)

RSS: [index] [pictures] Last build: 2026-04-17 22:49:00