| package tty |
| |
| import ( |
| "os" |
| "strings" |
| "unicode" |
| ) |
| |
| var linefeed = []byte{'\n'} |
| |
| func Open() (*TTY, error) { |
| return open("/dev/tty") |
| } |
| |
| func OpenDevice(path string) (*TTY, error) { |
| return open(path) |
| } |
| |
| func (tty *TTY) Raw() (func() error, error) { |
| return tty.raw() |
| } |
| |
| func (tty *TTY) MustRaw() func() error { |
| f, err := tty.raw() |
| if err != nil { |
| panic(err.Error()) |
| } |
| return f |
| } |
| |
| func (tty *TTY) Buffered() bool { |
| return tty.buffered() |
| } |
| |
| func (tty *TTY) ReadRune() (rune, error) { |
| return tty.readRune() |
| } |
| |
| func (tty *TTY) Close() error { |
| return tty.close() |
| } |
| |
| func (tty *TTY) Size() (int, int, error) { |
| return tty.size() |
| } |
| |
| func (tty *TTY) SizePixel() (int, int, int, int, error) { |
| return tty.sizePixel() |
| } |
| |
| func (tty *TTY) Input() *os.File { |
| return tty.input() |
| } |
| |
| func (tty *TTY) Output() *os.File { |
| return tty.output() |
| } |
| |
| // Display types. |
| const ( |
| displayNone = iota |
| displayRune |
| displayMask |
| ) |
| |
| func (tty *TTY) readString(displayType int) (string, error) { |
| rs := []rune{} |
| loop: |
| for { |
| r, err := tty.readRune() |
| if err != nil { |
| return "", err |
| } |
| switch r { |
| case 13: |
| break loop |
| case 8, 127: |
| if len(rs) > 0 { |
| rs = rs[:len(rs)-1] |
| if displayType != displayNone { |
| tty.Output().Write([]byte("\b \b")) |
| } |
| } |
| default: |
| if unicode.IsPrint(r) { |
| rs = append(rs, r) |
| switch displayType { |
| case displayRune: |
| tty.Output().Write([]byte(string(r))) |
| case displayMask: |
| tty.Output().Write([]byte{'*'}) |
| } |
| } |
| } |
| } |
| return string(rs), nil |
| } |
| |
| func (tty *TTY) ReadString() (string, error) { |
| defer tty.Output().Write(linefeed) |
| return tty.readString(displayRune) |
| } |
| |
| func (tty *TTY) ReadPassword() (string, error) { |
| defer tty.Output().Write(linefeed) |
| return tty.readString(displayMask) |
| } |
| |
| func (tty *TTY) ReadPasswordNoEcho() (string, error) { |
| defer tty.Output().Write(linefeed) |
| return tty.readString(displayNone) |
| } |
| |
| func (tty *TTY) ReadPasswordClear() (string, error) { |
| s, err := tty.readString(displayMask) |
| tty.Output().Write([]byte( |
| strings.Repeat("\b", len(s)) + |
| strings.Repeat(" ", len(s)) + |
| strings.Repeat("\b", len(s)))) |
| return s, err |
| } |
| |
| type WINSIZE struct { |
| W int |
| H int |
| } |
| |
| func (tty *TTY) SIGWINCH() <-chan WINSIZE { |
| return tty.sigwinch() |
| } |