Last active
June 5, 2022 20:32
-
-
Save deeplook/3f1a307fe29bb141c39e to your computer and use it in GitHub Desktop.
An experiment in speed reading texts in a terminal.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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:
Have a nice one!