# pardes_rotate spends a two-finger twist as the search-step keys. # # AppKit reports rotation counterclockwise-positive and the core reads clockwise # as `n`, so a NEGATIVE delta is the FORWARD step. That inversion is exactly the # kind of thing a unit test on the accumulator cannot catch and a golden can: # what the screen does is the assertion. # # One notch is 10 degrees (rotation_notch_degrees in src/macos.zig) and the # remainder is banked, which makes the pairs below exact rather than # approximate: -12 spends one notch and banks -2. start 30 100 wait 8000 Newcol Joincol wait 8000 $ stable 700 20000 # Twenty-four hits, not three. A coast is worth asserting only on a list long # enough to coast ALONG: `n` at the last match has nowhere to go, so on a # three-hit list the hardest possible flick and no flick at all produce the # same screen — which is a golden that would have passed before momentum # existed. printf reuses its format once per argument. text printf 'x MA''RK %s\nzz\n' 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 key enter wait 10000 MARK 24 stable 700 10000 key c-b stable 600 8000 # `/` types the pattern into the tag; Enter searches the pane's scrollback and # writes the hits into a +Search buffer, which is what n/N walk. text / stable 400 5000 text MARK stable 400 5000 key enter wait 10000 @p0: stable 700 15000 snap results # A gesture beginning re-zeros the dial, so travel left over from an earlier # twist cannot make the first degree of this one jump a match. rotate 0 # Clockwise: one notch of `n`, forward onto the first hit and selecting it. rotate -12 stable 700 15000 snap forward # ...and again, onto the second. Two steps out rather than one, because the # first hit is where the list already starts: stepping BACK from it has nowhere # to go, and a golden that cannot move is a golden that proves nothing about # which way the dial turns. rotate -12 stable 700 15000 snap forward2 # A new gesture, because the dial banks its remainder exactly like the scroll # accumulator does: two 12-degree notches leave -4 behind, so reversing INSIDE # the same twist would have to spend that first and 12 back would move nothing. # That hysteresis is wanted — it is what stops a thumb resettling on a notch # boundary from flip-flopping between two matches — and lifting the fingers is # how a hand clears it. rotate 0 # Counterclockwise: `N`. This must land back exactly on `forward`. rotate 12 stable 700 15000 snap back # And the other half of the contract: a twist IS the keystroke, so typing the # key the dial claims to send must go the same way the dial went. `n` here must # reproduce `forward2` — if the dial were sending something else, or the sign # were inverted, these two would part company. text n stable 700 15000 snap forward_by_key # ---- momentum ---- # # The dial coasts in proportion to how fast it was RELEASED, ramping up from # zero at the floor rather than switching on at it. Both halves of that are # here, and the gap argument is what makes them different: it is a real sleep # before the event, so libpardes measures a real speed off its clock. # # PLACED. Four degrees every 100 ms is 40 deg/s, under the 70 deg/s floor, so # lifting the fingers changes nothing at all — the twist itself has moved one # notch and that is where it stops. This is the case that has to hold: a slow # deliberate turn that kept sliding afterwards would be unusable. rotate 0 rotate -4 100 rotate -4 100 rotate -4 100 stable 700 15000 snap placed rotate_end stable 700 15000 # Byte-identical to `placed`, which is the whole assertion. snap placed_released # THROWN. The same twist delivered in 5 ms slices is hundreds of degrees a # second, so the release keeps the list walking after the fingers are gone. # # `snap` and then `rotate_end` with NO `stable` between them, which is not # impatience: a release is only a throw if it arrives while the hand is still # moving, and a 700 ms wait here would be a hand that stopped — which is # exactly what the PLACED case above already proves. The snapshot is a frame # read, far inside the 90 ms that separates the two. rotate 0 rotate -12 5 rotate -12 5 rotate -12 5 snap thrown rotate_end stable 700 15000 # ...and this one must NOT match `thrown`: the fling moved on its own, after # the gesture was over. That difference IS the feature. snap thrown_coasted draw rotate