tt/tt.go
2020-12-22 16:02:49 -05:00

143 lines
2.9 KiB
Go

package main
import (
"bytes"
"flag"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/gdamore/tcell"
"github.com/mattn/go-isatty"
)
func readConfig() map[string]string {
cfg := map[string]string{}
home, _ := os.LookupEnv("HOME")
path := filepath.Join(home, ".ttrc")
if b, err := ioutil.ReadFile(path); err == nil {
for _, ln := range bytes.Split(b, []byte("\n")) {
a := strings.SplitN(string(ln), ":", 2)
if len(a) == 2 {
cfg[a[0]] = strings.Trim(a[1], " ")
}
}
}
return cfg
}
func showReport(scr tcell.Screen, cpm, wpm int, accuracy float64) {
report := fmt.Sprintf("CPM: %d\nWPM: %d\nAccuracy: %.2f%%\n", cpm, wpm, accuracy)
scr.Clear()
drawCellsAtCenter(scr, stringToCells(report), -1)
scr.HideCursor()
scr.Show()
for {
if key, ok := scr.PollEvent().(*tcell.EventKey); ok && key.Key() == tcell.KeyEscape {
return
} else if ok && key.Key() == tcell.KeyCtrlC {
scr.Fini()
os.Exit(0)
}
}
}
func main() {
var n int
var csvMode bool
flag.IntVar(&n, "n", 50, "The number of random words which constitute the test.")
flag.BoolVar(&csvMode, "csv", false, "Print the test results to stdout in the form <cpm>,<wpm>,<accuracy>.")
flag.Usage = func() {
fmt.Println("\033[0;1mUsage:\033[0m\n")
fmt.Println("\033[0;1mKeybindings:\033[0m")
fmt.Println(" <esc> Restarts the test")
fmt.Println(" <C-c> Terminated tt\n")
fmt.Println("\033[0;1mOptions:\033[0m")
flag.PrintDefaults()
}
flag.Parse()
contentFn := func() string {
return randomText(n)
}
if !isatty.IsTerminal(os.Stdin.Fd()) {
b, err := ioutil.ReadAll(os.Stdin)
if err != nil {
panic(err)
}
contentFn = func() string {
return string(b)
}
}
scr, err := tcell.NewScreen()
if err != nil {
panic(err)
}
if err := scr.Init(); err != nil {
panic(err)
}
defer scr.Fini()
fgcol := newTcellColor("#8C8C8C")
bgcol := newTcellColor("#282828")
hicol2 := newTcellColor("#805b13")
hicol3 := newTcellColor("#b4801b")
hicol := newTcellColor("#ffffff")
errcol := newTcellColor("#a10705")
cfg := readConfig()
if c, ok := cfg["bgcol"]; ok {
bgcol = newTcellColor(c)
}
if c, ok := cfg["fgcol"]; ok {
fgcol = newTcellColor(c)
}
if c, ok := cfg["hicol"]; ok {
hicol = newTcellColor(c)
}
if c, ok := cfg["hicol2"]; ok {
hicol2 = newTcellColor(c)
}
if c, ok := cfg["hicol3"]; ok {
hicol3 = newTcellColor(c)
}
if c, ok := cfg["errcol"]; ok {
errcol = newTcellColor(c)
}
typer := NewTyper(scr, fgcol, bgcol, hicol, hicol2, hicol3, errcol)
for {
scr.Clear()
nerrs, ncorrect, t, completed := typer.Start([]string{contentFn()})
if completed {
cpm := int(float64(ncorrect) / (float64(t) / 60E9))
wpm := cpm / 5
accuracy := float64(ncorrect) / float64(nerrs+ncorrect) * 100
if csvMode {
scr.Fini()
fmt.Printf("%d,%d,%.2f\n", cpm, wpm, accuracy)
return
}
showReport(scr, cpm, wpm, accuracy)
}
}
}