In Part 3 we finally cross the line from “nice UI prototype” to an actual working typing trainer.
We implement the core typing behavior (including sane whitespace handling), wire up session timing, compute WPM and accuracy, and display results right inside the UI once you complete the text.
What We Covered
- Implemented the missing
Statemutations:apply_char()(including whitespace logic)apply_backspace()apply_backspace_word()(Ctrl+W behavior)
- Added session timing:
start_clock(),stop_clock(), andhas_started()
- Added the first real stats:
wpm()andaccuracy()
- Updated the UI to show a results line when the session is complete
- Enabled “start a new session” flow by returning a
should_loopflag from the UI runner
Design Insights
Whitespace Is the Hard Part (In Terminal Typing)
If you treat whitespace like any other character, terminal typing apps quickly feel annoying:
- multiple spaces are hard to see
- line breaks can be confusing
- “what does a wrong space even mean?”
So we handle whitespace intentionally:
- When the user types any whitespace, we append the matching whitespace from the target (all consecutive whitespace at that position).
- If there isn’t any target whitespace at that position, we fall back to a single space.
This keeps the experience consistent and prevents the input from drifting out of alignment.
“Hits” Are About Staying Error-Free
For accuracy we track two counters:
strokes: every time you type somethinghits: the strokes where the input is still a valid prefix of the target
So a “hit” is basically: after this keypress, are we still error-free? That’s a simple, intuitive baseline metric for early versions of the trainer.
Implementation Highlights
1) Typing input with smart whitespace
apply_char() is now real. It:
- stops input from exceeding target length
- expands whitespace into the matching whitespace run from the target
- increments
strokesandhitsbased on whether the input still matches the target prefix
2) Backspace that respects whitespace groups
Normal backspace removes at least one “character”, but if both the input and the target end with whitespace at the current position, we remove the whole matching whitespace run. That makes “undoing” spaces/newlines feel natural.
3) Ctrl+W word deletion
apply_backspace_word() behaves like a terminal-friendly “delete previous word”:
- remove trailing whitespace
- remove the word (non-whitespace)
- remove a single whitespace before the word (then stop)
This is one of those tiny UX details that instantly makes the tool feel more serious.
4) Session timing: start, stop, and elapsed time
We record the start time on the first meaningful input and stop when the session completes. Then we derive elapsed seconds for stats:
5) WPM + accuracy
WPM is computed with the standard “5 chars = 1 word” approximation:
wpm = (chars / 5) / (seconds / 60)
We also introduce chars_count() that treats consecutive whitespace as a single unit. The goal is to avoid weird stats spikes from runs of spaces/newlines in the target text.
Accuracy is the simple ratio:
hits / strokes(with a default of 100% if you haven’t typed anything yet)
6) Results UI + new session loop
When the text is complete, we render a results line (WPM + accuracy) and show a hint:
- Enter to quit
- Esc to start a new session
We also return should_loop from run_ui() so the outer application loop can restart cleanly without a full program restart.
What’s Next?
Now that TypeGym is interactive and can complete a run, we can start improving the “trainer” experience:
- better text sourcing (files, random samples, curated texts)
- command line arguments
Project Code
You will find the complete source code here: typegym