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
|
package main
import (
"encoding/json"
"net/http"
"net/url"
"strings"
"sync"
"code.rocketnine.space/tslocum/cview"
"github.com/gdamore/tcell/v2"
)
type company struct {
Name string `json:"name"`
}
func main() {
app := cview.NewApplication()
inputField := cview.NewInputField()
inputField.SetLabel("Enter a company name: ")
inputField.SetFieldWidth(30)
inputField.SetDoneFunc(func(key tcell.Key) {
app.Stop()
})
// Set up autocomplete function.
var mutex sync.RWMutex
prefixMap := make(map[string][]*cview.ListItem)
inputField.SetAutocompleteFunc(func(currentText string) []*cview.ListItem {
// Ignore empty text.
prefix := strings.TrimSpace(strings.ToLower(currentText))
if prefix == "" {
return nil
}
// Do we have entries for this text already?
mutex.Lock()
defer mutex.Unlock()
entries, ok := prefixMap[prefix]
if ok {
return entries
}
// No entries yet. Issue a request to the API in a goroutine.
go func() {
// Ignore errors in this demo.
url := "https://autocomplete.clearbit.com/v1/companies/suggest?query=" + url.QueryEscape(prefix)
res, err := http.Get(url)
if err != nil {
return
}
// Store the result in the prefix map.
var companies []*company
dec := json.NewDecoder(res.Body)
if err := dec.Decode(&companies); err != nil {
return
}
entries := make([]*cview.ListItem, 0, len(companies))
for _, c := range companies {
entries = append(entries, cview.NewListItem(c.Name))
}
mutex.Lock()
prefixMap[prefix] = entries
mutex.Unlock()
// Trigger an update to the input field.
inputField.Autocomplete()
// Also redraw the screen.
app.Draw()
}()
return nil
})
app.SetRoot(inputField, true)
if err := app.Run(); err != nil {
panic(err)
}
}
|