gob/shell/console/atom/input.go

335 lines
4.6 KiB
Go

package atom
import (
"bufio"
"io"
"strconv"
"time"
)
func timeout() <-chan time.Time {
return time.After(50 * time.Millisecond)
}
type input struct {
buf *bufio.Reader
next <-chan nchar
pending []Char
}
func (in *input) shift() (r Char) {
if len(in.pending) > 0 {
r, in.pending = in.pending[0], in.pending[1:]
}
return
}
func (in *input) push(r Char) Char {
in.pending = append(in.pending, r)
return r
}
func (in *input) clear() {
in.pending = in.pending[:0]
}
func (in *input) readRune() nchar {
if r, _, err := in.buf.ReadRune(); err != nil {
return ec(err)
} else {
return nc(r)
}
}
func newInput(r io.Reader) *input {
return &input{
buf: bufio.NewReader(r),
}
}
func (in *input) restart() {
next := make(chan nchar, 200)
go func() {
for {
n := in.readRune()
next <- n
r, ok := n.Ok()
needClose := !ok || r == Lf || r == Cr || r == C_C || r == C_D
if needClose {
close(next)
return
}
}
}()
in.next = next
}
func (in *input) isWaiting() bool {
return len(in.next) > 0
}
func (in *input) nextc() (n nchar) {
var ok bool
select {
case n, ok = <-in.next:
if !ok {
return ec(ErrInternal)
}
if r, ok := n.Ok(); ok {
in.push(r)
return nc(r)
}
}
return
}
func (in *input) nextt() (n nchar) {
var ok bool
select {
case n, ok = <-in.next:
if !ok {
return ec(ErrInternal)
if r, ok := n.Ok(); ok {
in.push(r)
return nc(r)
}
}
case <-timeout():
return ec(ErrTimeout)
}
return
}
func (in *input) escO() (key nkey) {
key = nk(KeyNil)
n := in.nextt()
if err, ok := n.Err(); ok {
if err == ErrTimeout {
return nk(keyS(AS_O))
}
return ek(err)
}
r, ok := n.Ok()
if !ok {
return
}
var s Sequence
if r >= '0' && r < '9' {
s = Sequence(r << 8)
n = in.nextt()
if err, ok := n.Err(); ok {
if err == ErrTimeout {
return
}
return ek(err)
}
r, _ = n.Ok()
}
s |= Sequence(r)
return nk(keyS(s))
}
func (in *input) escBracket() (key nkey) {
key = nk(KeyNil)
n := in.nextt()
if err, ok := n.Err(); ok {
if err == ErrTimeout {
return
}
return ek(err)
}
r, ok := n.Ok()
if !ok {
return
}
var s Sequence
switch r {
case 'A':
s = Up
case 'B':
s = Down
case 'C':
s = Right
case 'D':
s = Left
case 'F':
s = End
case 'H':
s = Home
case 'Z':
s = S_Tab
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return in.escNumberBracket(r)
default:
}
return nk(keyS(s))
}
func (in *input) escNumberBracket(r Char) (key nkey) {
key = nk(KeyNil)
num := []Char{r}
for {
n := in.nextt()
if err, ok := n.Err(); ok {
if err == ErrTimeout {
return
}
return ek(err)
}
r, ok := n.Ok()
if !ok {
return
}
switch r {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
num = append(num, r)
case '~':
return in.escTildeBracket(num)
case ';':
return in.escSemiColonBracket(num)
default:
return
}
}
return
}
func (in *input) escTildeBracket(num []Char) (key nkey) {
x, _ := strconv.ParseInt(string(num), 10, 32)
s := Sequence(x)
return nk(keyS(s))
}
func (in *input) escSemiColonBracket(num []Char) (key nkey) {
key = nk(KeyNil)
x, _ := strconv.ParseInt(string(num), 10, 32)
seqn := x != 1
var s Sequence
if seqn {
s = Sequence(x)
}
n := in.nextt()
if err, ok := n.Err(); ok {
if err == ErrTimeout {
return
}
return ek(err)
}
r, ok := n.Ok()
if !ok {
return
}
s |= Sequence(r << 8)
n = in.nextt()
if err, ok := n.Err(); ok {
if err == ErrTimeout {
return
}
return ek(err)
}
r, ok = n.Ok()
if !ok {
return
}
if r == '~' {
if !seqn {
return nk(KeyNil)
}
} else if !seqn {
s |= Sequence(r)
} else {
return
}
return nk(keyS(s))
}
func (in *input) nextChar() (key nkey) {
key = nk(KeyNil)
if len(in.pending) > 0 {
r := in.shift()
return nk(keyC(r))
}
n := in.nextc()
if err, ok := n.Err(); ok {
in.shift()
return ek(err)
}
r, ok := n.Ok()
if !ok {
return
}
if r != Esc {
in.shift()
return nk(keyC(r))
}
n = in.nextt()
if err, ok := n.Err(); ok {
if err == ErrTimeout {
return
}
return ek(err)
}
r, ok = n.Ok()
if !ok {
return
}
switch r {
case Bs:
key = nk(keyS(A_Bs))
case 'O':
key = in.escO()
case '[':
key = in.escBracket()
case 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z':
key = nk(keyS(Sequence(r << 16)))
//default:
// return
}
in.clear()
return
}