This repository has been archived by the owner on Jun 7, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.go
97 lines (93 loc) · 2.47 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package main
import (
"crypto/sha256"
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"time"
"github.com/gdamore/tcell"
"github.com/go-shiori/go-readability"
)
var defaultConfig = config{
wpm: 400,
strong: tcell.StyleDefault.Bold(true).Foreground(tcell.ColorRed),
// normal: tcell.StyleDefault.Reverse(true),
intervals: map[string]time.Duration{
".": time.Millisecond * time.Duration(500),
"(": time.Millisecond * time.Duration(200),
")": time.Millisecond * time.Duration(200),
"-": time.Millisecond * time.Duration(300),
",": time.Millisecond * time.Duration(300),
},
intervalStart: time.Second, intervalEnd: time.Second,
pauseStart: false, pauseEnd: false,
left: 10,
}
func main() {
var (
wpm int
savePos bool
resumePos bool
)
flag.IntVar(&wpm, "w", 400, "words per minute")
flag.BoolVar(&savePos, "p", true, "save position")
flag.BoolVar(&resumePos, "r", true, "try to resume at saved position")
flag.Parse()
// Get content
// TODO: stream mode where input is read gradually. Cos stdin
var content []string
var contentHash [sha256.Size]byte
var title string
switch flag.NArg() {
case 0:
title = "stdin"
fmt.Fprintf(os.Stderr, "%s: reading from stdin...\n", filepath.Base(os.Args[0]))
b, err := ioutil.ReadAll(os.Stdin)
if err != nil {
log.Fatalln("error reading stdin:", err)
}
contentHash = sha256.Sum256(b)
content = strings.Fields(string(b))
case 1:
article, err := readability.FromURL(flag.Arg(0), time.Second*3)
if err != nil {
log.Fatalln("error extracting article text:", err)
}
title = article.Title
contentHash = sha256.Sum256([]byte(article.TextContent))
content = strings.Fields(article.TextContent)
// TODO: handle images, code blocks, links, footnotes and other web stuff. Or not
}
// TODO: cannot resume a file if at end
conf := defaultConfig
conf.wpm = wpm
if resumePos {
p, err := lookupPos(contentHash)
if err != nil {
log.Fatalln("error finding last position:", err)
}
log.Printf("Resuming at word %d\n", p)
conf.startPos = p
}
// TODO: run speedread with a context, so we can survive kills/other signals
end, err := speedread(content, conf, title)
if savePos {
log.Println("Saving position...")
if end == len(content)-1 {
log.Println("reached end, saving position as 0")
err = writePos(contentHash, 0)
} else {
err = writePos(contentHash, end)
}
if err != nil {
log.Fatalln("Error saving position:", err)
}
}
if err != nil {
log.Fatal(err)
}
}