luv

Workshop wiki

tests.lisp

luvcraft/clim/tests.lisp

system luvcraft/test · 21 definitions · on GitHub

defpackage#:luvcraft.clim.tests
:use#:cl#:rove#:luvcraft.clim
:local-nicknames
#:luv#:luv
#:clim#:clim
#:climi#:clim-internals
in-package#:luvcraft.clim.tests
defunkey-press
key-name&keycharactermodifiers
make-instance'luv:canvas-key-press-event:timestamp0:key-namekey-name:charactercharacter:unshifted-charactercharacter:modifiersmodifiers
defclassrecording-focus
score:initarg:score:initformnil:readerrecording-focus-score
events:initformnil:accessorrecording-focus-events
defmethodluvcraft:luvcraft-focus-score
recording-focus-scorefocus
defmethodluvcraft:handle-luvcraft-focus-event
sessioncanvasevent
declare
ignoresessioncanvas
pushevent
recording-focus-eventsfocus
deftestkeys-resolve-to-named-commands
let
session
ok
equal'
com-toggle-inventory
luvcraft-key-commandsession
key-press:i:character#\i
ok
equal'
com-toggle-focus
ok
equal'
com-toggle-fullscreen
ok
equal'
com-toggle-tracy-capture
ok
equal'
luvcraft.clim::com-quit
luvcraft-key-commandsession
key-press:q:character#\q:modifiers'
:control
ok
equal'
com-execute-command
luvcraft-key-commandsession
key-press:x:character#\x:modifiers'
:meta
ok
equal'
com-start-walking:forward

A key nothing binds is not a command and must not be mistaken for one: LOOKUP-KEYSTROKE-COMMAND-ITEM answers with the gesture on a miss.

deftestphysical-dvorak-control-positions-do-not-collide
ok
equal'
#\,:forward
#\o:backward
#\a:left
#\e:right
:shift-left:sprint
:shift-right:sprint
let
session

Wayland supplies the Dvorak character as well as the physical scancode. The physical D position must walk even though its text is E.

ok
equal'
com-start-walking:right
luvcraft-key-commandsession
key-press:d:character#\e

Place remains the physical QWERTY E position, whose Dvorak text is a dot.

ok
equal'
luvcraft.clim::com-place-block
luvcraft-key-commandsession
key-press:e:character#\.
deftestm-x-searches-the-executable-command-vocabulary
let
ok
assoc"Toggle Phone"entries:test#'string=
ok
assoc"Place Block"entries:test#'string=
ok
assoc"Toggle Tracy Capture"entries:test#'string=
ok
assoc"Toggle Lobby Panel"entries:test#'string=
ok
assoc"Start Tracy Capture"entries:test#'string=
ok
assoc"Stop Tracy Capture"entries:test#'string=
ok
assoc"Open Last Tracy Capture"entries:test#'string=
ok
assoc"Reveal Last Tracy Capture"entries:test#'string=
ok
assoc"Export Presentation Timing"entries:test#'string=

Commands needing arguments will join M-x when it can ask for them; presenting them as executable before then would make a dishonest menu.

ok
null
assoc"Select Quickbar Slot"entries:test#'string=
ok
equal'
"Toggle Phone"

Words need not be adjacent, so the same finder scales to longer names.

ok
equal'
"Toggle Pointer Capture"
mapcar#'car
deftesta-digit-carries-its-slot-as-a-command-argument
let
session
ok
equal'
com-select-quickbar-slot3
luvcraft-key-commandsession
key-press:3:character#\3
ok
equal'
com-select-quickbar-slot1
luvcraft-key-commandsession
key-press:1:character#\1

The 0 key ends the number row as the tenth slot.

ok
equal'
com-select-quickbar-slot10
luvcraft-key-commandsession
key-press:0:character#\0
deftesta-command-runs-inline-on-the-calling-thread
let*
session
blocks
luvcraft:block-inventory-blocks
luvcraft:luvcraft-session-inventorysession

The whole design rests on this: with no FRAME-PROCESS of its own, the frame applies a command on the thread that looked it up, so a command may touch session state exactly as an event handler may.

ok
null
climi::frame-processframe
ok
eq
secondblocks
luvcraft:luvcraft-session-selected-blocksession

An unbound key changes nothing and says so.

ok
eq
secondblocks
luvcraft:luvcraft-session-selected-blocksession

Dispatch: which layer a key reaches.

deftesttab-enters-focus-and-shift-tab-always-leaves-it
let*
session
far
make-instance'recording-focus:score4.0
near
make-instance'recording-focus:score1.0
tab
tab-release
make-instance'luv:canvas-key-release-event:timestamp0:key-name:tab
shift-tab
key-press:tab:modifiers'
:shift
ok
eqnear
luvcraft:luvcraft-session-modal-focussession

The release matching the focus keystroke is swallowed; ordinary Tab afterwards belongs to the focus, which is where Bash completion lives.

luv:handle-canvas-eventsessionniltab-release
luv:handle-canvas-eventsessionniltab-release
ok
equal
listtab-releasetab
recording-focus-eventsnear

Shift-Tab is in the window table, so it leaves even a focus that takes every other key.

luv:handle-canvas-eventsessionnilshift-tab
ok
null
luvcraft:luvcraft-session-modal-focussession
ok
null
recording-focus-eventsfar
deftesta-focus-with-no-table-of-its-own-takes-every-remaining-key
let
session
focus
make-instance'recording-focus
i
key-press:i:character#\i
ok
equal
listi
recording-focus-eventsfocus
"a shell being typed into gets its own I"

Unfocused, the same key is the world's verb rather than text, and never reaches the object that used to hold focus.

ok
equal'
com-toggle-inventory
defunkey-release
key-name&keycharactermodifiers
make-instance'luv:canvas-key-release-event:timestamp0:key-namekey-name:charactercharacter:unshifted-charactercharacter:modifiersmodifiers
deftestwalking-is-a-start-and-a-stop
let*
session
intent
luvcraft:luvcraft-session-movement-intentsession
luv:handle-canvas-eventsessionnil
key-press:w:character
ifdvorak#\,#\w
ok
=1d0
luvcraft:movement-intent-axisintent:forward:backward

Holding the opposite direction is standing still, and letting go of it leaves the first one still held -- which one axis could not remember.

luv:handle-canvas-eventsessionnil
key-press:s:character
ifdvorak#\o#\s
ok
zerop
luvcraft:movement-intent-axisintent:forward:backward
luv:handle-canvas-eventsessionnil
key-release:s:character
ifdvorak#\o#\s
ok
=1d0
luvcraft:movement-intent-axisintent:forward:backward
luv:handle-canvas-eventsessionnil
key-release:w:character
ifdvorak#\,#\w
deftesta-movement-key-means-the-same-thing-however-it-is-modified
let*
session
intent
luvcraft:luvcraft-session-movement-intentsession

Shift makes a player sprint; it does not make W into another key.

luv:handle-canvas-eventsessionnil
key-press:shift-left:modifiers'
:shift
luv:handle-canvas-eventsessionnil
key-press:w:character:modifiers'
:shift
luv:handle-canvas-eventsessionnil
key-release:shift-left:modifiers'
:shift
deftestspace-owes-the-player-a-jump
let*
session
intent
luvcraft:luvcraft-session-movement-intentsession
ok
luvcraft:movement-intent-jump-requested-pintent
deftestthe-number-row-selects-through-the-command-layer
let*
session
blocks
luvcraft:block-inventory-blocks
luvcraft:luvcraft-session-inventorysession
luv:handle-canvas-eventsessionnil
key-press:8:character#\8
ok
eq
nth7blocks
luvcraft:luvcraft-session-selected-blocksession

A repeat is the same keystroke still held, so a verb does not fire again.

luv:handle-canvas-eventsessionnil
key-press:1:character#\1
ok
eq
firstblocks
luvcraft:luvcraft-session-selected-blocksession
luv:handle-canvas-eventsessionnil
make-instance'luv:canvas-key-press-event:timestamp0:key-name:8:character#\8:unshifted-character#\8:repeat-pt
ok
eq
firstblocks
luvcraft:luvcraft-session-selected-blocksession

The legend says what the tables say.

deftestthe-legend-is-read-off-the-command-tables
let
ok
equal'
"Moving""In the world""At a wall""Any time"
mapcar#'carsections
flet
keys-for
titlelabel
cdr
assoclabel
cdr
assoctitlesections:test#'string=
:test#'string=

A direction is its own line, because walking forward and sprinting are different things to do even though one command performs both.

ok
equal
keys-for"Moving""walk forward"
ok
equal
keys-for"Moving""walk right"

The arrows look rather than walk: one merged row, all four keys.

ok
equal'
"↑""↓""←""→"
keys-for"In the world""look"
ok
equal'
"Shift"
keys-for"Moving""sprint"
ok
equal'
"Space"
keys-for"Moving""jump"
ok
equal'
"I"
keys-for"In the world""toggle inventory"
ok
equal'
"Esc"
keys-for"In the world""show keys"
ok
equal'
"Alt-X"
keys-for"In the world""execute command"
ok
equal'
"F9"
keys-for"Any time""toggle tracy capture"
ok
equal'
"F11"
keys-for"Any time""toggle fullscreen"

Modifiers are printed, and :ANY is not: it is noise on every row.

ok
equal'
"Shift-Tab"
keys-for"Any time""leave focus"

A wall's modes are reachable, and say by which key.

ok
equal'
"Cmd-1"
keys-for"At a wall""shell mode"
ok
equal'
"Cmd-2"
keys-for"At a wall""film mode"

Ten slots share one line, because nobody needs to be told about each.

ok
equal'
"1""2""3""4""5""6""7""8""9""0"
keys-for"In the world""select block"

A command owned by the movement layer is not repeated under the world that inherits it.

ok
null
keys-for"In the world""walk forward"
deftesta-rebound-key-changes-what-the-legend-says
let
table
clim:find-command-table'luvcraft.clim::luvcraft-world
unwind-protect
progn
clim:add-keystroke-to-command-tabletable'
#\y
:command'
luvcraft.clim::com-toggle-inventory
:errorpnil
ok
member"Y"
cdr
assoc"toggle inventory"
cdr
assoc"In the world":test#'string=
:test#'string=
:test#'string=
"the legend follows the table rather than a written-down list"
clim:remove-keystroke-from-command-tabletable'
#\y
:errorpnil