Skip to content

Instantly share code, notes, and snippets.

@kipawaa
Created September 26, 2025 22:03
Show Gist options
  • Select an option

  • Save kipawaa/87d81730b8e953b07a68412126aeb969 to your computer and use it in GitHub Desktop.

Select an option

Save kipawaa/87d81730b8e953b07a68412126aeb969 to your computer and use it in GitHub Desktop.
Vim WPM
" Provides a WPM function that returns an estimate of the current typing speed.
" intended use is with the status bar: add this file to `.vim/plugin` and
" `set statusline += WPM: %{WPM()}` in your `.vimrc`.
" WARNING: due to possible initialization issues, the first reported values
" can be wildly inaccurate.
" uses a circular buffer of `num_samples` wordcounts and `num_samples` times
" to sample WPM over (approximately) `num_samples` seconds and update the
" output of the `WPM` function (approximately) every 1s.
" The amount of time to estimate over.
" you can change this, but testing showed that somewhere from 7-10 is best for
" practical estimates.
let s:num_samples = 10
" use a circular buffer of `num_samples` different wordcounts
let s:word_counts = map(range(s:num_samples), {-> wordcount().words})
" similarly, use a circular buffer of `num_samples` times
let s:times = map(range(s:num_samples), {-> reltime()})
" initialize wpm, index and sample_time
let s:wpm = 0
let s:i = 0
let s:last_sample_time = reltime()
function WPM()
" Returns the current WPM estimated by the change in wordcount over
" (approximately) the last `num_samples` seconds.
" Output is updated (approximately) every 1 second
" update s:wpm only if it's been at least 1s since the last update
if reltimefloat(reltime(s:last_sample_time)) > 1
" get change in word count
let l:word_delta = max([wordcount().words - s:word_counts[s:i], 0])
" get time since last sample
let l:time_delta = reltime(s:times[s:i])
" set wpm
let s:wpm = (l:word_delta / reltimefloat(l:time_delta)) * 60
" reset word count and timer
let s:word_counts[s:i] = wordcount().words
let s:times[s:i] = reltime()
" reset last sample time
let s:last_sample_time = reltime()
" increment buffer
let s:i = (s:i + 1) % s:num_samples
endif
" return most recent WPM value
return s:wpm
endfunction
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment