Add prompt.Input and prompt.Choose
This commit is contained in:
parent
2921d1d259
commit
0194c52454
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/c-bata/go-prompt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func executor(in string) {
|
||||
|
@ -11,13 +12,18 @@ func executor(in string) {
|
|||
}
|
||||
|
||||
func completer(in string) []prompt.Suggest {
|
||||
args := strings.Split(in, " ")
|
||||
last := args[0]
|
||||
if len(args) > 0 {
|
||||
last = args[len(args) - 1]
|
||||
}
|
||||
s := []prompt.Suggest{
|
||||
{Text: "users", Description: "user table"},
|
||||
{Text: "sites", Description: "sites table"},
|
||||
{Text: "articles", Description: "articles table"},
|
||||
{Text: "comments", Description: "comments table"},
|
||||
}
|
||||
return prompt.FilterHasPrefix(s, in, true)
|
||||
return prompt.FilterHasPrefix(s, last, true)
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/c-bata/go-prompt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fruits := []string{"Apple", "Banana", "Bilberry", "Coconuts"}
|
||||
|
||||
fmt.Println("What fruits do you like?")
|
||||
f := prompt.Choose("> ", fruits)
|
||||
fmt.Println("You like " + f)
|
||||
}
|
|
@ -2,7 +2,7 @@ package prompt
|
|||
|
||||
import "strings"
|
||||
|
||||
type CompletionFilter func([]Suggest, string, bool) []Suggest
|
||||
type Filter func([]Suggest, string, bool) []Suggest
|
||||
|
||||
func FilterHasPrefix(completions []Suggest, sub string, ignoreCase bool) []Suggest {
|
||||
if sub == "" {
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
func TestFilter(t *testing.T) {
|
||||
var scenarioTable = []struct {
|
||||
scenario string
|
||||
filter CompletionFilter
|
||||
filter Filter
|
||||
list []Suggest
|
||||
substr string
|
||||
ignoreCase bool
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package prompt
|
||||
|
||||
func dummyExecutor(in string) { return }
|
||||
|
||||
func Input(prefix string, completer Completer, opts ...option) string {
|
||||
pt := New(dummyExecutor, completer)
|
||||
pt.renderer.prefixTextColor = DefaultColor
|
||||
pt.renderer.prefix = prefix
|
||||
|
||||
for _, opt := range opts {
|
||||
if err := opt(pt); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
return pt.Input()
|
||||
}
|
||||
|
||||
func Choose(prefix string, choices []string, opts ...option) string {
|
||||
completer := newChoiceCompleter(choices, FilterHasPrefix)
|
||||
pt := New(dummyExecutor, completer)
|
||||
pt.renderer.prefixTextColor = DefaultColor
|
||||
pt.renderer.prefix = prefix
|
||||
|
||||
for _, opt := range opts {
|
||||
if err := opt(pt); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
return pt.Input()
|
||||
}
|
||||
|
||||
func newChoiceCompleter(choices []string, filter Filter) Completer {
|
||||
s := make([]Suggest, len(choices))
|
||||
for i := range choices {
|
||||
s[i] = Suggest{Text: choices[i]}
|
||||
}
|
||||
return func(x string) []Suggest {
|
||||
return filter(s, x, true)
|
||||
}
|
||||
}
|
58
prompt.go
58
prompt.go
|
@ -34,21 +34,11 @@ func (p *Prompt) Run() {
|
|||
p.setUp()
|
||||
defer p.tearDown()
|
||||
|
||||
if os.Getenv(envEnableLog) != "true" {
|
||||
log.SetOutput(ioutil.Discard)
|
||||
} else if f, err := os.OpenFile(logfile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666); err != nil {
|
||||
log.SetOutput(ioutil.Discard)
|
||||
} else {
|
||||
defer f.Close()
|
||||
log.SetOutput(f)
|
||||
log.Println("[INFO] Logging is enabled.")
|
||||
}
|
||||
|
||||
p.renderer.Render(p.buf, p.completion)
|
||||
|
||||
bufCh := make(chan []byte, 128)
|
||||
stopReadBufCh := make(chan struct{})
|
||||
go p.readBuffer(bufCh, stopReadBufCh)
|
||||
go readBuffer(bufCh, stopReadBufCh)
|
||||
|
||||
exitCh := make(chan int)
|
||||
winSizeCh := make(chan *WinSize)
|
||||
|
@ -74,7 +64,7 @@ func (p *Prompt) Run() {
|
|||
|
||||
// Set raw mode
|
||||
p.in.Setup()
|
||||
go p.readBuffer(bufCh, stopReadBufCh)
|
||||
go readBuffer(bufCh, stopReadBufCh)
|
||||
} else {
|
||||
p.completion.Update(p.buf.Text())
|
||||
p.renderer.Render(p.buf, p.completion)
|
||||
|
@ -170,7 +160,47 @@ func (p *Prompt) feed(b []byte) (shouldExit bool, exec *Exec) {
|
|||
return
|
||||
}
|
||||
|
||||
func (p *Prompt) Input() string {
|
||||
p.setUp()
|
||||
defer p.tearDown()
|
||||
|
||||
p.renderer.Render(p.buf, p.completion)
|
||||
bufCh := make(chan []byte, 128)
|
||||
stopReadBufCh := make(chan struct{})
|
||||
go readBuffer(bufCh, stopReadBufCh)
|
||||
|
||||
for {
|
||||
select {
|
||||
case b := <-bufCh:
|
||||
if shouldExit, e := p.feed(b); shouldExit {
|
||||
p.renderer.BreakLine(p.buf)
|
||||
return ""
|
||||
} else if e != nil {
|
||||
// Stop goroutine to run readBuffer function
|
||||
stopReadBufCh <- struct{}{}
|
||||
return e.input
|
||||
} else {
|
||||
p.completion.Update(p.buf.Text())
|
||||
p.renderer.Render(p.buf, p.completion)
|
||||
}
|
||||
default:
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Prompt) setUp() {
|
||||
// Logging
|
||||
if os.Getenv(envEnableLog) != "true" {
|
||||
log.SetOutput(ioutil.Discard)
|
||||
} else if f, err := os.OpenFile(logfile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666); err != nil {
|
||||
log.SetOutput(ioutil.Discard)
|
||||
} else {
|
||||
defer f.Close()
|
||||
log.SetOutput(f)
|
||||
log.Println("[INFO] Logging is enabled.")
|
||||
}
|
||||
|
||||
p.in.Setup()
|
||||
p.renderer.Setup()
|
||||
p.renderer.UpdateWinSize(p.in.GetWinSize())
|
||||
|
@ -181,7 +211,7 @@ func (p *Prompt) tearDown() {
|
|||
p.renderer.TearDown()
|
||||
}
|
||||
|
||||
func (p *Prompt) readBuffer(bufCh chan []byte, stopCh chan struct{}) {
|
||||
func readBuffer(bufCh chan []byte, stopCh chan struct{}) {
|
||||
buf := make([]byte, 1024)
|
||||
|
||||
log.Printf("[INFO] readBuffer start")
|
||||
|
@ -189,7 +219,7 @@ func (p *Prompt) readBuffer(bufCh chan []byte, stopCh chan struct{}) {
|
|||
time.Sleep(10 * time.Millisecond)
|
||||
select {
|
||||
case <-stopCh:
|
||||
log.Print("[INFO] stop p.readBuffer")
|
||||
log.Print("[INFO] stop readBuffer")
|
||||
return
|
||||
default:
|
||||
if n, err := syscall.Read(syscall.Stdin, buf); err == nil {
|
||||
|
|
Loading…
Reference in New Issue