summaryrefslogtreecommitdiff
path: root/vendor/github.com/chzyer/readline/utils.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/chzyer/readline/utils.go')
-rw-r--r--vendor/github.com/chzyer/readline/utils.go277
1 files changed, 277 insertions, 0 deletions
diff --git a/vendor/github.com/chzyer/readline/utils.go b/vendor/github.com/chzyer/readline/utils.go
new file mode 100644
index 000000000..af4e00521
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/utils.go
@@ -0,0 +1,277 @@
+package readline
+
+import (
+ "bufio"
+ "bytes"
+ "container/list"
+ "fmt"
+ "os"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+ "unicode"
+)
+
+var (
+ isWindows = false
+)
+
+const (
+ CharLineStart = 1
+ CharBackward = 2
+ CharInterrupt = 3
+ CharDelete = 4
+ CharLineEnd = 5
+ CharForward = 6
+ CharBell = 7
+ CharCtrlH = 8
+ CharTab = 9
+ CharCtrlJ = 10
+ CharKill = 11
+ CharCtrlL = 12
+ CharEnter = 13
+ CharNext = 14
+ CharPrev = 16
+ CharBckSearch = 18
+ CharFwdSearch = 19
+ CharTranspose = 20
+ CharCtrlU = 21
+ CharCtrlW = 23
+ CharCtrlY = 25
+ CharCtrlZ = 26
+ CharEsc = 27
+ CharEscapeEx = 91
+ CharBackspace = 127
+)
+
+const (
+ MetaBackward rune = -iota - 1
+ MetaForward
+ MetaDelete
+ MetaBackspace
+ MetaTranspose
+)
+
+// WaitForResume need to call before current process got suspend.
+// It will run a ticker until a long duration is occurs,
+// which means this process is resumed.
+func WaitForResume() chan struct{} {
+ ch := make(chan struct{})
+ var wg sync.WaitGroup
+ wg.Add(1)
+ go func() {
+ ticker := time.NewTicker(10 * time.Millisecond)
+ t := time.Now()
+ wg.Done()
+ for {
+ now := <-ticker.C
+ if now.Sub(t) > 100*time.Millisecond {
+ break
+ }
+ t = now
+ }
+ ticker.Stop()
+ ch <- struct{}{}
+ }()
+ wg.Wait()
+ return ch
+}
+
+func Restore(fd int, state *State) error {
+ err := restoreTerm(fd, state)
+ if err != nil {
+ // errno 0 means everything is ok :)
+ if err.Error() == "errno 0" {
+ return nil
+ } else {
+ return err
+ }
+ }
+ return nil
+}
+
+func IsPrintable(key rune) bool {
+ isInSurrogateArea := key >= 0xd800 && key <= 0xdbff
+ return key >= 32 && !isInSurrogateArea
+}
+
+// translate Esc[X
+func escapeExKey(key *escapeKeyPair) rune {
+ var r rune
+ switch key.typ {
+ case 'D':
+ r = CharBackward
+ case 'C':
+ r = CharForward
+ case 'A':
+ r = CharPrev
+ case 'B':
+ r = CharNext
+ case 'H':
+ r = CharLineStart
+ case 'F':
+ r = CharLineEnd
+ case '~':
+ if key.attr == "3" {
+ r = CharDelete
+ }
+ default:
+ }
+ return r
+}
+
+type escapeKeyPair struct {
+ attr string
+ typ rune
+}
+
+func (e *escapeKeyPair) Get2() (int, int, bool) {
+ sp := strings.Split(e.attr, ";")
+ if len(sp) < 2 {
+ return -1, -1, false
+ }
+ s1, err := strconv.Atoi(sp[0])
+ if err != nil {
+ return -1, -1, false
+ }
+ s2, err := strconv.Atoi(sp[1])
+ if err != nil {
+ return -1, -1, false
+ }
+ return s1, s2, true
+}
+
+func readEscKey(r rune, reader *bufio.Reader) *escapeKeyPair {
+ p := escapeKeyPair{}
+ buf := bytes.NewBuffer(nil)
+ for {
+ if r == ';' {
+ } else if unicode.IsNumber(r) {
+ } else {
+ p.typ = r
+ break
+ }
+ buf.WriteRune(r)
+ r, _, _ = reader.ReadRune()
+ }
+ p.attr = buf.String()
+ return &p
+}
+
+// translate EscX to Meta+X
+func escapeKey(r rune, reader *bufio.Reader) rune {
+ switch r {
+ case 'b':
+ r = MetaBackward
+ case 'f':
+ r = MetaForward
+ case 'd':
+ r = MetaDelete
+ case CharTranspose:
+ r = MetaTranspose
+ case CharBackspace:
+ r = MetaBackspace
+ case 'O':
+ d, _, _ := reader.ReadRune()
+ switch d {
+ case 'H':
+ r = CharLineStart
+ case 'F':
+ r = CharLineEnd
+ default:
+ reader.UnreadRune()
+ }
+ case CharEsc:
+
+ }
+ return r
+}
+
+func SplitByLine(start, screenWidth int, rs []rune) []string {
+ var ret []string
+ buf := bytes.NewBuffer(nil)
+ currentWidth := start
+ for _, r := range rs {
+ w := runes.Width(r)
+ currentWidth += w
+ buf.WriteRune(r)
+ if currentWidth >= screenWidth {
+ ret = append(ret, buf.String())
+ buf.Reset()
+ currentWidth = 0
+ }
+ }
+ ret = append(ret, buf.String())
+ return ret
+}
+
+// calculate how many lines for N character
+func LineCount(screenWidth, w int) int {
+ r := w / screenWidth
+ if w%screenWidth != 0 {
+ r++
+ }
+ return r
+}
+
+func IsWordBreak(i rune) bool {
+ switch {
+ case i >= 'a' && i <= 'z':
+ case i >= 'A' && i <= 'Z':
+ case i >= '0' && i <= '9':
+ default:
+ return true
+ }
+ return false
+}
+
+func GetInt(s []string, def int) int {
+ if len(s) == 0 {
+ return def
+ }
+ c, err := strconv.Atoi(s[0])
+ if err != nil {
+ return def
+ }
+ return c
+}
+
+type RawMode struct {
+ state *State
+}
+
+func (r *RawMode) Enter() (err error) {
+ r.state, err = MakeRaw(GetStdin())
+ return err
+}
+
+func (r *RawMode) Exit() error {
+ if r.state == nil {
+ return nil
+ }
+ return Restore(GetStdin(), r.state)
+}
+
+// -----------------------------------------------------------------------------
+
+func sleep(n int) {
+ Debug(n)
+ time.Sleep(2000 * time.Millisecond)
+}
+
+// print a linked list to Debug()
+func debugList(l *list.List) {
+ idx := 0
+ for e := l.Front(); e != nil; e = e.Next() {
+ Debug(idx, fmt.Sprintf("%+v", e.Value))
+ idx++
+ }
+}
+
+// append log info to another file
+func Debug(o ...interface{}) {
+ f, _ := os.OpenFile("debug.tmp", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
+ fmt.Fprintln(f, o...)
+ f.Close()
+}