1package main
2
3import (
4	"io/ioutil"
5	"path/filepath"
6	"regexp"
7
8	"github.com/xyproto/vt100"
9)
10
11// corpus will grep all files matching the glob for "searchword.*" and return a list of what matched "*".
12// I thought this might be slow, but initial tests shows that this appears to be fast enough for interactive usage.
13func corpus(searchword, glob string) []string {
14	wordCount := make(map[string]int)
15
16	filenames, err := filepath.Glob(glob)
17	if err != nil {
18		return []string{}
19	}
20
21	re := regexp.MustCompile(`[[:^alpha:]]` + searchword + `\.([[:alpha:]]*)`)
22
23	var data []byte
24	var highestCount int
25	for _, filename := range filenames {
26		data, err = ioutil.ReadFile(filename)
27		if err != nil {
28			continue
29		}
30		submatches := re.FindAllStringSubmatch(string(data), -1)
31		for _, submatch := range submatches {
32			word := submatch[1]
33			if _, ok := wordCount[word]; ok {
34				wordCount[word]++
35				if wordCount[word] > highestCount {
36					highestCount = wordCount[word]
37				}
38			} else {
39				wordCount[word] = 1
40				if wordCount[word] > highestCount {
41					highestCount = wordCount[word]
42				}
43			}
44		}
45	}
46
47	// Copy the words from the map to a string slice, such
48	// that the most frequent words appear first.
49	sl := make([]string, len(wordCount))
50	slIndex := 0
51	for i := highestCount; i >= 0; i-- {
52		for word, count := range wordCount {
53			if count == i && len(word) > 0 {
54				sl[slIndex] = word
55				slIndex++
56			}
57		}
58	}
59
60	return sl
61}
62
63// SuggestMode lets the user tab through the suggested words
64func (e *Editor) SuggestMode(c *vt100.Canvas, status *StatusBar, tty *vt100.TTY, suggestions []string) string {
65	if len(suggestions) == 0 {
66		return ""
67	}
68
69	suggestIndex := 0
70	s := suggestions[suggestIndex]
71
72	status.ClearAll(c)
73	status.SetMessage("Suggest: " + s)
74	status.ShowNoTimeout(c, e)
75
76	var doneChoosing bool
77	for !doneChoosing {
78		key := tty.String()
79		switch key {
80		case "c:9", "↓", "→": // tab, down arrow or right arrow
81			// Cycle suggested words
82			suggestIndex++
83			if suggestIndex == len(suggestions) {
84				suggestIndex = 0
85			}
86			s = suggestions[suggestIndex]
87			status.ClearAll(c)
88			status.SetMessage("Suggest: " + s)
89			status.ShowNoTimeout(c, e)
90		case "↑", "←": // up arrow or left arrow
91			// Cycle suggested words (one back)
92			suggestIndex--
93			if suggestIndex < 0 {
94				suggestIndex = len(suggestions) - 1
95			}
96			s = suggestions[suggestIndex]
97			status.ClearAll(c)
98			status.SetMessage("Suggest: " + s)
99			status.ShowNoTimeout(c, e)
100		case "c:8", "c:127": // ctrl-h or backspace
101			fallthrough
102		case "c:27", "c:17": // esc, ctrl-q or backspace
103			s = ""
104			fallthrough
105		case "c:13", "c:32": // return or space
106			doneChoosing = true
107		}
108	}
109	status.ClearAll(c)
110	// The chosen word
111	return s
112}
113