Merge ae591692bb
into 82a9122745
This commit is contained in:
commit
1dc872f06f
|
@ -3,13 +3,94 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
prompt "github.com/c-bata/go-prompt"
|
||||
"github.com/c-bata/go-prompt/internal/term"
|
||||
)
|
||||
|
||||
type KeyPress struct {
|
||||
Key prompt.Key
|
||||
Bytes []byte
|
||||
}
|
||||
|
||||
type Parser struct {
|
||||
Input chan rune
|
||||
Out chan KeyPress
|
||||
}
|
||||
|
||||
func (p *Parser) Feed(r rune) {
|
||||
p.Input <- r
|
||||
}
|
||||
|
||||
func (p *Parser) Start() {
|
||||
prefix := bytes.NewBuffer(nil)
|
||||
retry := false
|
||||
for {
|
||||
if retry {
|
||||
retry = false
|
||||
} else {
|
||||
in, ok := <-p.Input
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
prefix.WriteRune(in)
|
||||
}
|
||||
|
||||
if prefix.Len() > 0 {
|
||||
isPrefixOfLongerMatch := false
|
||||
for _, s := range prompt.ASCIISequences {
|
||||
if bytes.HasPrefix(s.ASCIICode, prefix.Bytes()) && bytes.Compare(s.ASCIICode, prefix.Bytes()) != 0 {
|
||||
isPrefixOfLongerMatch = true
|
||||
break
|
||||
}
|
||||
}
|
||||
match := prompt.GetKey(prefix.Bytes())
|
||||
if !isPrefixOfLongerMatch && match != prompt.NotDefined {
|
||||
p.Out <- KeyPress{Key: match, Bytes: prefix.Bytes()}
|
||||
prefix.Reset()
|
||||
} else if !isPrefixOfLongerMatch && match == prompt.NotDefined {
|
||||
found := false
|
||||
retry = true
|
||||
|
||||
prefixRunes := []rune(prefix.String())
|
||||
for i := len(prefixRunes); i > 0; i-- {
|
||||
prefixBytes := []byte(string(prefixRunes[:i]))
|
||||
match = prompt.GetKey(prefixBytes)
|
||||
if match != prompt.NotDefined {
|
||||
p.Out <- KeyPress{Key: match, Bytes: prefixBytes}
|
||||
for j := 0; j < i; j++ {
|
||||
_, _, _ = prefix.ReadRune()
|
||||
}
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
r, _, err := prefix.ReadRune()
|
||||
if err == io.EOF {
|
||||
continue // don't reach here.
|
||||
}
|
||||
p.Out <- KeyPress{Key: match, Bytes: []byte(string(r))}
|
||||
_, _, _ = prefix.ReadRune()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func NewParser() *Parser {
|
||||
return &Parser{
|
||||
Input: make(chan rune, 1),
|
||||
Out: make(chan KeyPress, 1),
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := term.SetRaw(syscall.Stdin); err != nil {
|
||||
fmt.Println(err)
|
||||
|
@ -17,31 +98,45 @@ func main() {
|
|||
}
|
||||
defer term.Restore()
|
||||
|
||||
bufCh := make(chan []byte, 128)
|
||||
go readBuffer(bufCh)
|
||||
fmt.Print("> ")
|
||||
p := NewParser()
|
||||
sigquit := make(chan os.Signal, 1)
|
||||
signal.Notify(sigquit, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)
|
||||
|
||||
go p.Start()
|
||||
|
||||
r := bufio.NewReader(os.Stdin)
|
||||
go func() {
|
||||
for {
|
||||
c, _, err := r.ReadRune()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
p.Feed(c)
|
||||
}
|
||||
close(p.Input)
|
||||
}()
|
||||
|
||||
for {
|
||||
b := <-bufCh
|
||||
if key := prompt.GetKey(b); key == prompt.NotDefined {
|
||||
fmt.Printf("Key '%s' data:'%#v'\n", string(b), b)
|
||||
} else {
|
||||
if key == prompt.ControlC {
|
||||
fmt.Println("exit.")
|
||||
select {
|
||||
case keypress := <-p.Out:
|
||||
if keypress.Key == prompt.NotDefined {
|
||||
fmt.Printf("Key '%s' data:'%#v'\n", string(keypress.Bytes), keypress.Bytes)
|
||||
} else {
|
||||
fmt.Printf("Key '%s' data:'%#v'\n", keypress.Key, keypress.Bytes)
|
||||
if keypress.Key == prompt.ControlC {
|
||||
return
|
||||
}
|
||||
}
|
||||
if keypress.Key == prompt.ControlC {
|
||||
return
|
||||
}
|
||||
fmt.Printf("Key '%s' data:'%#v'\n", key, b)
|
||||
}
|
||||
fmt.Print("> ")
|
||||
}
|
||||
}
|
||||
|
||||
func readBuffer(bufCh chan []byte) {
|
||||
buf := make([]byte, 1024)
|
||||
|
||||
for {
|
||||
if n, err := syscall.Read(syscall.Stdin, buf); err == nil {
|
||||
bufCh <- buf[:n]
|
||||
case <-sigquit:
|
||||
close(p.Input)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
2
input.go
2
input.go
|
@ -96,7 +96,7 @@ var ASCIISequences = []*ASCIICode{
|
|||
{Key: F3, ASCIICode: []byte{0x1b, 0x4f, 0x52}},
|
||||
{Key: F4, ASCIICode: []byte{0x1b, 0x4f, 0x53}},
|
||||
|
||||
{Key: F1, ASCIICode: []byte{0x1b, 0x4f, 0x50, 0x41}}, // Linux console
|
||||
{Key: F1, ASCIICode: []byte{0x1b, 0x4f, 0x5b, 0x41}}, // Linux console
|
||||
{Key: F2, ASCIICode: []byte{0x1b, 0x5b, 0x5b, 0x42}}, // Linux console
|
||||
{Key: F3, ASCIICode: []byte{0x1b, 0x5b, 0x5b, 0x43}}, // Linux console
|
||||
{Key: F4, ASCIICode: []byte{0x1b, 0x5b, 0x5b, 0x44}}, // Linux console
|
||||
|
|
Loading…
Reference in New Issue