---
layout: ../Site.layout.js
---
# A minimal GUI keyboard display in [McCLIM](https://mcclim.common-lisp.dev/main.html) common lisp interface manager

```
(defparameter *approximate-keyboard*
'(((1) (2) (3) (4) (5) (6) (7) (8) (9) (0))
((q) (w) (e) (r) (t) (y) (u) (i) (o) (p))
((a) (s) (d) (f) (g) (h) (j) (k) (l) (|;|))
((z) (x) (c) (v) (b) (n) (m) (|,|) (|.|) (|/|))))
```
In at least some cases of laptop keyboard, this is pretty close to what you've got alphanumerically; I expect one's fingers hang around some of these keys. It's going to be a little ugly but I wanted to do a quick keystrokes (i.e. shortcuts/hotkeys) display for my [NicCLIM map editor](/lispgames/trying-nicclim), which in its upcoming version 2 now has lots of keyboard accelerators as I guess we'll see in another moment.
I guess you're reasonably set up so the next two lines make sense. Otherwise: [my lisp intro](/fundamental/installing-lisp-etc/), [McCLIM's git README](https://codeberg.org/McCLIM/McCLIM).
```
(require :mcclim)
(in-package :clim-user)
```
## An `application-frame` with that keyboard.
I figure it should go in a slot of the frame.
```
(define-application-frame key-frame ()
((keyboard :initarg :keyboard))
(:pane :application :display-function 'display-keyboard)
(:default-initargs
:keyboard '(((1) (2) (3) (4) (5) (6) (7) (8) (9) (0))
((q) (w) (e) (r) (t) (y) (u) (i) (o) (p))
((a) (s) (d) (f) (g) (h) (j) (k) (l) (|;|))
((z) (x) (c) (v) (b) (n) (m) (|,|) (|.|) (|/|)))))
```
## The `:display-function` `'display-keyboard`
```
(defun display-keyboard
(frame pane)
(with-slots
(keyboard)
frame
(formatting-table
(pane)
(loop :for row :in keyboard :do
(formatting-row
(pane)
(loop
:for cell :in row :do
(formatting-cell
(pane)
(updating-output
(pane)
(surrounding-output-with-border
(pane)
(with-text-style
(pane
(make-text-style :sans-serif :roman :tiny))
(loop
:for symbol :in cell
:for hack := nil :then (fresh-line pane) :do
(present symbol 'symbol
:stream pane))))))))))))
```
## Look at that
```
(find-application-frame 'key-frame)
```
Could be worse for the defaults.
## Changing the key text
So we absolutely do not want to deface the intuitive keyboard layout list. What I *have* is a list of keyboard accelerator associated commands. Since each keyboard key is unique, I guess we can just use `loop`..`nsubst`.
My new [nicclim](https://lispy-gopher-show.itch.io/nicclim) shortcuts (listen, I program experimentally)
```
(defparameter *v2-nicclim-shortcuts*
'(((b) (c-s-b execute list))
((q) (c-s-q funcall))
((w) (c-s-w apply))
((e) (c-s-e gets))
((r) (c-s-r setsgets))
((t) (c-s-t change player))
((a) (c-s-a extract player))
((s) (c-s-s doas))
((d) (c-s-d doas list))
((c) (c-s-c rect union))
((z) (c-s-z rect intersection))
((x) (c-s-x rect difference))
((f) (c-s-f cur1 rotatef))
((v) (c-s-v note location))))
```
# Open the same frame with these changes [`nsubst`](http://www.lispworks.com/reference/HyperSpec/Body/f_substc.htm)ituted
```
(find-application-frame
'key-frame
:keyboard
(loop
:with new-keyboard := (copy-list
*approximate-keyboard*)
:for (old new) :in *v2-nicclim-shortcuts*
:do
(nsubst new old new-keyboard :test 'equal)
:finally
(return new-keyboard)))
```
# Conclusion
I can't say we did anything profoundly deep, but it worked like I thought it would- first, the realistically laid out list datastructure (my friend [notptr](https://social.cyberia9.org/notes/abyc9k5qmhae058d) says they normally write their game maps like this in the first place, so at least someone does it), then using a keyboard arguement with [common lisp's `loop`](https://www.lispworks.com/documentation/HyperSpec/Body/m_loop.htm) and `nsubst` to add [keyboard accelerator](https://www.lispworks.com/documentation/lw80/clim/clim-ch11-2.htm) descriptions.
The [common lisp interface manager spec](http://bauhh.dyndns.org:8000/clim-spec/index.html)'s [dynamic table resizing](https://www.lispworks.com/documentation/lwu41/climuser/GUID_281.HTM#HEADING281-0) did what I hoped it would do. I am not contending I should win any particular awards for graphic design. Maybe you will.
If you want to *take the next step* with McCLIM because this simple example only whet your voracious appetite, the next thing to do is to make the table cells [sensitive-inferiors](https://www.lispworks.com/documentation/lw80/clim/clim-ch6-3.htm#CLIM) (when choosing a command for example).
# Fin.
Let's [get on the mastodon](https://gamerplus.org/@screwlisp/115105693171271215), as per usual please.
Oh, if you didn't attend live/listen already, the sbcl-powered biggest-ever cosmic string simulation done by the Tufts Supercomputer for their astrophysics department (interview with Ken Olum) really answers this question: "who actually uses common lisp these days?" https://communitymedia.video/w/9kysH4ZwVuP4J4erZozqFT