Skip to content

Instantly share code, notes, and snippets.

@deeplook
Last active June 5, 2022 20:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save deeplook/3f1a307fe29bb141c39e to your computer and use it in GitHub Desktop.
Save deeplook/3f1a307fe29bb141c39e to your computer and use it in GitHub Desktop.
An experiment in speed reading texts in a terminal.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
An experiment in speed reading texts in a terminal.
It implements a "poor man's" version running in a plain terminal. The speed
is given in wpm, words per second. KeyboardInterrupts are captured for pausing
the presentation. At the end a summary is printed. This toy project is much
inspired by an iOS app named ReadQuick:
https://itunes.apple.com/en/app/readquick-speed-reader-for/id515138359?mt=8
Possible extensions:
- automatically increase text and/or terminal size during the presentation
This code should work in any Unix terminal and with Python 2 and 3 alike,
e.g.
python speedread.py -h
python speedread.py --test
python3 speedread.py --test
python speedread.py --path /path/to/file.txt
python3 speedread.py --speed 100 --text "The quick brown fox... has retired."
"""
from __future__ import print_function
import os
import sys
import time
import subprocess
try:
import argparse
except ImportError:
print("Error: package 'argparse' not found. Please install 'argparse'")
print("if you are running Python 2! You can do this with:")
print(" pip install argparse")
sys.exit()
# control sequence for clearing the terminal
p = subprocess.Popen('clear', shell=False, stdout=subprocess.PIPE)
clear = p.stdout.read().strip().decode(encoding='UTF-8') # '\x1b[H\x1b[2J'
# taken from http://en.wikipedia.org/wiki/Speed_reading
SAMPLE_TEXT = """
Speed reading courses and books take a variety of approaches to the concept
of reading comprehension. Some courses and books claim that good comprehension
is essential to speed reading, and that comprehension will improve with speed
reading. Special non-standardized reading comprehension questionnaires are
provided in order to convince the reader of the effects of the program. Some
courses advise that while comprehension is important, it should not be measured
or promoted. Speed reading courses variously claim that not all information in
text needs to be covered while speed reading. Some claim that speed reading
involves skipping text (exactly as has been measured during studies on
skimming), whereas other speed reading promoters who claim that all of the
text is processed, but with some or most becoming subconsciously processed.
Similarly, some courses claim that text should be serially processed whereas
others say that information should be processed in a more haphazard or ad hoc
fashion."""
# rename input function named differently in Python 2 and 3
try:
input = raw_input
except NameError:
pass
def present(text, wpm=250, show_summary=True):
"Print a text word by word in a terminal with a certain speed."
wps = wpm / 60.
t_wait_sec = 1 / wps
t0 = time.time()
t_total = 0
for i, word in enumerate(text.strip().split()):
try:
print(clear)
print(word)
time.sleep(t_wait_sec)
except KeyboardInterrupt:
t_total += (time.time() - t0)
try:
msg = '\nPausing at current speed of %d wpm.' % wpm
msg += '\nEnter an integer to change the wpm '
msg += '(<enter> key to continue, ^C or ^D to quit): '
response = input(msg)
try:
wpm = int(response)
wps = wpm / 60.
t_wait_sec = 1 / wps
except ValueError:
pass
except (KeyboardInterrupt, EOFError):
print('')
sys.exit(0)
t0 = time.time()
t_total += (time.time() - t0)
if show_summary:
print('')
print("number of words: %d" % (i + 1))
print("total time: %g" % t_total)
print("desired (initial) speed: %g wpm" % wpm)
print("average speed: %g wpm" % ((i + 1) / t_total * 60))
if __name__ == "__main__":
desc = "This is a poor man's speed reading script for the terminal."
parser = argparse.ArgumentParser(description=desc)
paa = parser.add_argument
paa("--text", metavar='TEXT',
help="Set text to be presented.", nargs='?', default='')
paa("-s", "--speed", metavar='SPEED', dest="speed", type=int,
help="Set presentation speed in words per minute (wpm).", default=250)
paa("-f", "--file", metavar='PATH', dest="path", type=str,
help="Set path of text file to present.")
num_words = len(SAMPLE_TEXT.strip().split())
paa("-t", "--test", action='store_true',
help="Present a sample text (%d words)." % num_words)
options = parser.parse_args()
if options.test:
options.text = SAMPLE_TEXT
if options.text:
present(options.text, options.speed)
elif options.path:
text = open(options.path).read().strip()
present(text, options.speed)
@dabruh
Copy link

dabruh commented Jun 5, 2022

This is great! Have you done any more work on this? I'd really love to replace the Jetzt browser extension by this, but I'm missing some features.

What comes to mind from having used Jetzt + other things:

  • Spacebar to pause
  • Up/down arrows to change WPM
  • Left and right arrows to jump between sentences
  • Slight pause at the end of a sentence.
  • You can probably find some more by using Jetzt.
  • Read from stdin

Have a nice one!

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