8000 feat: continuous timed mode — stream words until the clock stops (#6) by hindriix · Pull Request #26 · jrnxf/thokr · GitHub
[go: up one dir, main page]

Skip to content

feat: continuous timed mode — stream words until the clock stops (#6) - #26

Merged
jrnxf merged 12 commits into
jrnxf:mainfrom
hindriix:feat/continuous-timed-mode
Oct 29, 2026
Merged

jrnxf merged 12 commits into
jrnxf:mainfrom
hindriix:feat/continuous-timed-mode

Conversation

@hindriix
@hindriix hindriix commented Jul 22, 2026 •
Copy link
Copy Markdown
Contributor

What

Makes timed tests (-s) a true Monkeytype-style time attack: instead of ending the moment you reach the end of a fixed prompt, fresh words stream in as you type and the test ends only when the clock hits zero.

Closes #6.

Why

Today, thokr -s 60 over the default 15 words is over in a couple of seconds — the timer is really just a cap, not a duration. A timed test people actually want runs for the full time and keeps feeding you words. #6 has asked for this ("continually load new words to meet time limit / scroll lines") since early 2023.

How

  • thok: a refill_words pool; when it's non-empty, refill_if_needed() tops the prompt up whenever the runway ahead of the cursor runs low, and has_finished() ends the test on the timer only — never by reaching the end of the words.
  • main: seeds the pool from the active language, but only in the default word mode with -s. A custom prompt (-p) or sentences (-f) are finite text, so they still end at their own length.
  • ui: because the prompt is now unbounded, the running view scrolls a fixed 3-line window (anchored to the cursor line) instead of expanding to fit — the layout stays centered and stable. The hardware-cursor math tracks the same window so it can't drift from the rendered text.

Verification

  • cargo build, cargo test, cargo clippy, cargo fmt --check all clean; new unit tests cover refill-keeps-runway, timer-only finish, and that non-continuous mode still finishes by length.
  • Manually driven through a PTY: the timer counts down, the prompt streams well past the initial buffer, and the test ends on the clock with a normal results screen.

Backwards compatible: non--s runs and -p/-f are unchanged.

Timed tests (`-s`) previously ended the moment you reached the end of a
fixed prompt, so a 60s run over 15 words was over in a couple seconds.
This makes `-s` a true Monkeytype-style time attack: words stream in as
you type and the test ends only when the timer expires. Closes the
long-standing request in issue jrnxf#6.

- thok: add a `refill_words` pool; `refill_if_needed()` tops the prompt
  up whenever the runway ahead of the cursor runs low, and continuous
  tests finish on the timer only (never by length).
- main: seed the refill pool from the active language in the default word
  mode with `-s`; a custom prompt (`-p`) or sentences (`-f`) stay finite.
- ui: render a scrolled 3-line viewport for the (now unbounded) prompt so
  the layout stays centered and stable; cursor math tracks the window.
- docs + `--help`: describe continuous mode; refresh examples.
- tests: cover refill, timer-only finish, and non-continuous length finish.
@hindriix
hindriix force-pushed the feat/continuous-timed-mode branch from f4dd032 to 6c24147 Compare July 25, 2026 06:07
Adds a `-d` / `--death-mode` flag. With it on, the test finishes the
instant an incorrect character is typed, checked ahead of the usual
length/timer rules so it beats even a running timer.

Practicing with zero tolerance for errors is a well-known way to build
accuracy (and, in turn, speed). This revives the idea from the
long-open PR jrnxf#18 with a focused implementation and tests.

- thok: `death_mode` flag on `Thok`; `has_finished` returns early on any
  incorrect input when it's set.
- main: `-d` flag wired through `App::new`/`reset`.
- docs: README example + `--help` entry.
- tests: mistake ends it, off tolerates mistakes, and it overrides a
  running timer.
jrnxf added 10 commits October 29, 2026 11:46
A run that dies after a fraction of a second would otherwise be logged as
an absurdly high wpm. Thok::died() is the one place that says a test ended
on a mistake; has_finished uses it, and save_if_finished skips the history
append for a died run. Clean runs in death mode still log.
…the new ui

- lang.rs: word_pool() replaces the old lang/mod.rs one
- the 3-line prompt window is applied to the wrapped lines before the
  layout, and char_cell on that slice gives the cursor row
- the prompt is topped up once when the pool is set, so -w 0 -s 5 no longer
  panics on the first key and the prompt stays its full height from the
  first frame; an empty prompt does not start with a space
- the death-mode check stays above the continuous timer-only rule in
  has_finished, so a mistake still ends a -d -s run
- regenerate the snapshots that the window now affects
- README: no em dashes, table realigned
Instead of the wpm results, a run that died shows a YOU DIED heading, the
expected character against the key pressed, the prompt around the mistake
with the word it was in underlined, and how far the run got in words,
characters and time. A clean death-mode run and a mistake outside death
mode keep the normal results screen. Retry and new-test keys are unchanged.
The refill was sized in characters, so on a wide screen the prompt started
under three lines and a later refill grew it mid-test, jumping the centred
block up a row. The refill now works in wrapped lines: the screen reports
its line width on every draw, and the prompt is topped up until a full
window of lines follows the cursor's line, at the start, after each key
and after a resize.
The block (heading, what went wrong, the prompt around it, how far the run
got) is centred on the screen, every line on one axis, with the key hints
bottom left where the results screen has them. The website's snapshot check
skips the death screen, which the page has no death mode to draw.
Main now holds death mode (squash-merged from its own PR), whose tree matches
what this branch already merged from the death-mode branch, so the result
keeps everything from main plus this PR's changes.
@jrnxf
jrnxf merged commit 72274a5 into jrnxf:main Oct 29, 2026
5 checks passed
@jrnxf
jrnxf commented Oct 29, 2026
Copy link
Copy Markdown
Owner

Thanks @hindriix, continuous timed mode is a great addition and fixes #6.

I merged the current main into your branch (plus the death mode branch, so -d -s could be tested) and pushed these on top, with your commits left as they are:

  • Ported it to the rewritten UI: the 3-line window now slices the wrapped lines, and the cursor row comes from that slice.
  • Fixed a crash: thokr -w 0 -s 5 panicked on the first key because the prompt was empty. The prompt is now filled when the test is created, which also stops it jumping from 2 to 3 lines on the first keystroke.
  • Fixed the prompt gaining a line mid-test: a timed test now always holds a full 3-line window of words at the current width, including after a resize, with a test.
  • A mistake still ends a -d -s run, with a test.
  • Regenerated the four UI snapshots that the 3-line window changes, and tidied the README (no em dashes, table lined up).

Merged, thanks again!

@jrnxf jrnxf mentioned this pull request Oct 29, 2026
@jrnxf
jrnxf commented Oct 29, 2026
Copy link
Copy Markdown
Owner

Shipped in v0.7.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

continually load new words to meet time limit / scroll lines

2 participants

0