Skip to content
PressboardKit
All posts

Engineering

Measuring the double-space period shortcut

Two spaces become a full stop — but only if the second one arrives in time. iOS exposes no such value to read, so we built an instrument, measured it against the native keyboard, and wrote down the error bar as well as the answer.

30 July 2026 · 4 min read · The PressboardKit team

Type a word, then two spaces, and iOS gives you a full stop and a space. It is one of those behaviours nobody configures and everybody relies on, which makes it a good test of whether an engine is really matching the system keyboard or merely doing something reasonable.

Ours was doing something reasonable. It looked at the text and nothing else: if the document ended in a space and another space arrived, expand. That is correct in the common case and wrong in two others.

It fired after an arbitrarily long pause. Type a word, a space, put the phone down, come back a minute later, hit space — full stop. And it fired on a space that was never typed at all: paste a string with a trailing space, hit space, and the shortcut expands a sentence the user did not write.

Native does neither, because native has a time limit. The question was what the limit is.

Measuring instead of guessing

There is no API for this and no way to read it out of the accessibility tree. What there is, is a keyboard you can drive and a text field you can read back — which is all this particular behaviour needs, because unlike a long-press threshold it leaves its answer in the text. So it can be bracketed: find an interval where it still fires, find one where it no longer does, and close the gap between them.

That produced a bracket, and the default the engine ships sits inside it, at the end that our instrument’s own error can only have pushed the wrong way. It is exposed as a parameter, so an integrator can move it, or turn the whole behaviour off and have neither the shortcut nor its window.

Alongside the window came the rule about which space counts. The shortcut now needs to know when the user last typed a space — and only a space they actually typed on the keyboard has such a moment. One that arrived from the pasteboard, or was inserted automatically, or was already in the field when the keyboard appeared, has none. With no moment recorded, the shortcut does not expand. Not “expands after a long delay”: does not expand.

The caveat, stated plainly

Every number we get this way is an upper bound, and the honest thing is to say so.

A UI test harness adds its own latency between synthesised taps, and that latency lands on the same side of the measurement as the thing being measured: it makes the gap between two spaces look longer than the gap the keyboard actually experienced. So the real window is at most what we measured, and is probably shorter by whatever the harness costs.

We do know roughly what a harness can cost, because a different measurement with the same problem let us calibrate it. There, the instrument was pointed at both the native keyboard and our own — whose value we already knew from the source — through the same harness, in the same host app. The difference between the known value and the measured one is the harness overhead, and subtracting it brought native and our own keyboard into agreement within the resolution of the measurement.

That self-calibration was deliberately not carried over to the period-shortcut window. The two instruments are not the same shape — one holds a press and waits inside it, the other times a gap between two separate taps — and an overhead measured for one is not evidence about the other. The honest statement is the bracket plus the caveat, which is what the repository records and what the default was chosen from.

Why bother

Because the alternative is a plausible constant, and plausible constants are how an engine drifts away from the thing it is imitating: one reasonable decision at a time, none of them individually wrong, until the keyboard feels almost right and nobody can say why.

The same wave of work settled which keys on the numeric page send you back to the letters. The intuition is “punctuation that ends a word”. The measurement — taken by tapping every key on the native page in turn — is that exactly one of them does it, and it is not one anybody would have guessed. It makes sense the moment you see it. It would never have been reasoned out.

Neither value is interesting on its own, and neither is published here. What is worth publishing is that both are written down, both have a test that fails if the behaviour changes, and both are parameters rather than constants — because an integrator building something that is not a general-purpose keyboard may well want a different answer.