github.com/xyproto/orbiton/v2@v2.65.12-0.20240516144430-e10a419274ec/suggest.go (about) 1 package main 2 3 import ( 4 "os" 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. 13 func 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 corpusRegex := regexp.MustCompile(`[[:^alpha:]]` + searchword + `\.([[:alpha:]]*)`) 22 23 var data []byte 24 var highestCount int 25 for _, filename := range filenames { 26 data, err = os.ReadFile(filename) 27 if err != nil { 28 continue 29 } 30 submatches := corpusRegex.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 64 func (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 }