...
1 package tty
2
3 import (
4 "os"
5 "strings"
6 "unicode"
7 )
8
9 func Open() (*TTY, error) {
10 return open("/dev/tty")
11 }
12
13 func OpenDevice(path string) (*TTY, error) {
14 return open(path)
15 }
16
17 func (tty *TTY) Raw() (func() error, error) {
18 return tty.raw()
19 }
20
21 func (tty *TTY) MustRaw() func() error {
22 f, err := tty.raw()
23 if err != nil {
24 panic(err.Error())
25 }
26 return f
27 }
28
29 func (tty *TTY) Buffered() bool {
30 return tty.buffered()
31 }
32
33 func (tty *TTY) ReadRune() (rune, error) {
34 return tty.readRune()
35 }
36
37 func (tty *TTY) Close() error {
38 return tty.close()
39 }
40
41 func (tty *TTY) Size() (int, int, error) {
42 return tty.size()
43 }
44
45 func (tty *TTY) SizePixel() (int, int, int, int, error) {
46 return tty.sizePixel()
47 }
48
49 func (tty *TTY) Input() *os.File {
50 return tty.input()
51 }
52
53 func (tty *TTY) Output() *os.File {
54 return tty.output()
55 }
56
57
58 const (
59 displayNone = iota
60 displayRune
61 displayMask
62 )
63
64 func (tty *TTY) readString(displayType int) (string, error) {
65 rs := []rune{}
66 loop:
67 for {
68 r, err := tty.readRune()
69 if err != nil {
70 return "", err
71 }
72 switch r {
73 case 13:
74 break loop
75 case 8, 127:
76 if len(rs) > 0 {
77 rs = rs[:len(rs)-1]
78 if displayType != displayNone {
79 tty.Output().WriteString("\b \b")
80 }
81 }
82 default:
83 if unicode.IsPrint(r) {
84 rs = append(rs, r)
85 switch displayType {
86 case displayRune:
87 tty.Output().WriteString(string(r))
88 case displayMask:
89 tty.Output().WriteString("*")
90 }
91 }
92 }
93 }
94 return string(rs), nil
95 }
96
97 func (tty *TTY) ReadString() (string, error) {
98 defer tty.Output().WriteString("\n")
99 return tty.readString(displayRune)
100 }
101
102 func (tty *TTY) ReadPassword() (string, error) {
103 defer tty.Output().WriteString("\n")
104 return tty.readString(displayMask)
105 }
106
107 func (tty *TTY) ReadPasswordNoEcho() (string, error) {
108 defer tty.Output().WriteString("\n")
109 return tty.readString(displayNone)
110 }
111
112 func (tty *TTY) ReadPasswordClear() (string, error) {
113 s, err := tty.readString(displayMask)
114 tty.Output().WriteString(
115 strings.Repeat("\b", len(s)) +
116 strings.Repeat(" ", len(s)) +
117 strings.Repeat("\b", len(s)))
118 return s, err
119 }
120
121 type WINSIZE struct {
122 W int
123 H int
124 }
125
126 func (tty *TTY) SIGWINCH() <-chan WINSIZE {
127 return tty.sigwinch()
128 }
129
View as plain text