-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
232 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,24 @@ | ||
module github.com/sbreitf1/go-console | ||
|
||
go 1.15 | ||
go 1.17 | ||
|
||
require ( | ||
github.com/davecgh/go-spew v1.1.1 // indirect | ||
github.com/eiannone/keyboard v0.0.0-20200508000154-caf4b762e807 | ||
github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203 | ||
github.com/gdamore/tcell v1.4.0 | ||
github.com/mattn/go-runewidth v0.0.9 // indirect | ||
github.com/nsf/termbox-go v0.0.0-20200418040025-38ba6e5628f1 | ||
github.com/stretchr/testify v1.6.1 | ||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 | ||
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 | ||
golang.org/x/text v0.3.4 // indirect | ||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect | ||
github.com/nsf/termbox-go v1.1.1 | ||
github.com/stretchr/testify v1.8.0 | ||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 | ||
golang.org/x/sys v0.0.0-20220913175220-63ea55921009 | ||
) | ||
|
||
require ( | ||
github.com/davecgh/go-spew v1.1.1 // indirect | ||
github.com/gdamore/encoding v1.0.0 // indirect | ||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect | ||
github.com/mattn/go-runewidth v0.0.13 // indirect | ||
github.com/pmezard/go-difflib v1.0.0 // indirect | ||
github.com/rivo/uniseg v0.4.2 // indirect | ||
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 // indirect | ||
golang.org/x/text v0.3.7 // indirect | ||
gopkg.in/yaml.v3 v3.0.1 // indirect | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,51 @@ | ||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= | ||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/eiannone/keyboard v0.0.0-20200508000154-caf4b762e807 h1:jdjd5e68T4R/j4PWxfZqcKY8KtT9oo8IPNVuV4bSXDQ= | ||
github.com/eiannone/keyboard v0.0.0-20200508000154-caf4b762e807/go.mod h1:Xoiu5VdKMvbRgHuY7+z64lhu/7lvax/22nzASF6GrO8= | ||
github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203 h1:XBBHcIb256gUJtLmY22n99HaZTz+r2Z51xUPi01m3wg= | ||
github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203/go.mod h1:E1jcSv8FaEny+OP/5k9UxZVw9YFWGj7eI4KR/iOBqCg= | ||
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= | ||
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= | ||
github.com/gdamore/tcell v1.4.0 h1:vUnHwJRvcPQa3tzi+0QI4U9JINXYJlOz9yiaiPQ2wMU= | ||
github.com/gdamore/tcell v1.4.0/go.mod h1:vxEiSDZdW3L+Uhjii9c3375IlDmR05bzxY404ZVSMo0= | ||
github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac= | ||
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= | ||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= | ||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= | ||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= | ||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= | ||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= | ||
github.com/nsf/termbox-go v0.0.0-20200418040025-38ba6e5628f1 h1:lh3PyZvY+B9nFliSGTn5uFuqQQJGuNrD0MLCokv09ag= | ||
github.com/nsf/termbox-go v0.0.0-20200418040025-38ba6e5628f1/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ= | ||
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= | ||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= | ||
github.com/nsf/termbox-go v1.1.1 h1:nksUPLCb73Q++DwbYUBEglYBRPZyoXJdrj5L+TkjyZY= | ||
github.com/nsf/termbox-go v1.1.1/go.mod h1:T0cTdVuOwf7pHQNtfhnEbzHbcNyCEcVU4YPpouCbVxo= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= | ||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= | ||
github.com/rivo/uniseg v0.4.2 h1:YwD0ulJSJytLpiaWua0sBDusfsCZohxjxzVTYjwxfV8= | ||
github.com/rivo/uniseg v0.4.2/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= | ||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= | ||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E= | ||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | ||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= | ||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= | ||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= | ||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM= | ||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= | ||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= | ||
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 h1:a/mKvvZr9Jcc8oKfcmgzyp7OwF73JPWsQLvH1z2Kxck= | ||
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= | ||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/sys v0.0.0-20220913175220-63ea55921009 h1:PuvuRMeLWqsf/ZdT1UUZz0syhioyv1mzuFZsXs4fvhw= | ||
golang.org/x/sys v0.0.0-20220913175220-63ea55921009/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 h1:Q5284mrmYTpACcm+eAKjKJH48BBwSyfJqmmGDTtT8Vc= | ||
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= | ||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= | ||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= | ||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= | ||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= | ||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= | ||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
//go:build darwin | ||
|
||
package console | ||
|
||
import ( | ||
"os" | ||
"syscall" | ||
"unicode/utf8" | ||
"unsafe" | ||
|
||
"golang.org/x/sys/unix" | ||
) | ||
|
||
const ioctlReadTermios = unix.TIOCGETA | ||
const ioctlWriteTermios = unix.TIOCSETA | ||
|
||
func withoutEcho(f func() error) error { | ||
fd := int(os.Stdin.Fd()) | ||
|
||
termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
newState := *termios | ||
newState.Lflag &^= unix.ECHO | ||
newState.Lflag |= unix.ICANON | unix.ISIG | ||
newState.Iflag |= unix.ICRNL | ||
if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, &newState); err != nil { | ||
return err | ||
} | ||
|
||
defer unix.IoctlSetTermios(fd, ioctlWriteTermios, termios) | ||
|
||
return f() | ||
} | ||
|
||
func supportsColors() bool { | ||
return true | ||
} | ||
|
||
var ( | ||
ttyIn *os.File | ||
ttyOut *os.File | ||
ttyOldTermios syscall.Termios | ||
ttyBuffer []byte | ||
) | ||
|
||
func beginReadKey() error { | ||
in, err := os.OpenFile("/dev/tty", syscall.O_RDONLY, 0) | ||
if err != nil { | ||
return err | ||
} | ||
ttyIn = in | ||
out, err := os.OpenFile("/dev/tty", syscall.O_WRONLY, 0) | ||
if err != nil { | ||
ttyIn.Close() | ||
return err | ||
} | ||
ttyOut = out | ||
|
||
if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(in.Fd()), ioctlReadTermios, uintptr(unsafe.Pointer(&ttyOldTermios))); err != 0 { | ||
ttyIn.Close() | ||
ttyOut.Close() | ||
return err | ||
} | ||
newTermios := ttyOldTermios | ||
newTermios.Iflag &^= syscall.ISTRIP | syscall.INLCR | syscall.ICRNL | syscall.IGNCR | syscall.IXOFF | ||
newTermios.Lflag &^= syscall.ECHO | syscall.ICANON | ||
//TODO catch Ctrl+C | ||
if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(in.Fd()), ioctlWriteTermios, uintptr(unsafe.Pointer(&newTermios))); err != 0 { | ||
ttyIn.Close() | ||
ttyOut.Close() | ||
return err | ||
} | ||
|
||
ttyBuffer = []byte{} | ||
return nil | ||
} | ||
|
||
func readKey() (Key, rune, error) { | ||
buf := make([]byte, 4) | ||
var bufLen int | ||
if len(ttyBuffer) > 0 { | ||
// use buffered data from previous readKey call | ||
bufLen = len(ttyBuffer) | ||
for i := 0; i < len(ttyBuffer); i++ { | ||
buf[i] = ttyBuffer[i] | ||
} | ||
ttyBuffer = []byte{} | ||
|
||
} else { | ||
// read new buffer | ||
len, err := ttyIn.Read(buf) | ||
if err != nil { | ||
return 0, 0, err | ||
} | ||
|
||
// huge amounts of data leading to multiple keys at once in the buffer will probably be caused by inserting text | ||
// thus, explicit actions keys are assumed to be received in a single read call | ||
|
||
// handle escape key sequences | ||
if buf[0] == 27 { | ||
if len == 1 { | ||
return KeyEscape, '^', nil | ||
} | ||
|
||
if len == 2 { | ||
// malformed escape sequence | ||
return KeyEscape, rune(buf[1]), nil | ||
} | ||
|
||
switch buf[2] { | ||
case 65: | ||
return KeyUp, 0, nil | ||
case 66: | ||
return KeyDown, 0, nil | ||
case 68: | ||
return KeyLeft, 0, nil | ||
case 67: | ||
return KeyRight, 0, nil | ||
|
||
default: | ||
// unknown escape sequence | ||
return KeyEscape, rune(buf[2]), nil | ||
} | ||
} | ||
|
||
bufLen = len | ||
} | ||
|
||
// handle some special chars | ||
switch buf[0] { | ||
case '\r': | ||
ttyBuffer = buf[1:bufLen] | ||
return KeyEnter, '\n', nil | ||
case '\u007f': | ||
ttyBuffer = buf[1:bufLen] | ||
return KeyBackspace, '\r', nil | ||
case '\t': | ||
ttyBuffer = buf[1:bufLen] | ||
return KeyTab, '\t', nil | ||
case ' ': | ||
ttyBuffer = buf[1:bufLen] | ||
return KeySpace, ' ', nil | ||
case '\x03': | ||
ttyBuffer = buf[1:bufLen] | ||
return KeyCtrlC, 0, nil | ||
} | ||
|
||
// assemble utf8-rune | ||
for i := 1; i < 4; i++ { | ||
// return complete buffer rune | ||
if utf8.FullRune(buf[:i]) { | ||
// return remainder after rune | ||
ttyBuffer = buf[i:bufLen] | ||
break | ||
} | ||
|
||
if i >= bufLen { | ||
// need to fill the buffer from tty input to complete the rune | ||
if _, err := ttyIn.Read(buf[i : i+1]); err != nil { | ||
return 0, 0, err | ||
} | ||
bufLen++ | ||
} | ||
} | ||
|
||
r, _ := utf8.DecodeRune(buf) | ||
return 0, r, nil | ||
} | ||
|
||
func endReadKey() error { | ||
if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(ttyIn.Fd()), ioctlWriteTermios, uintptr(unsafe.Pointer(&ttyOldTermios))); err != 0 { | ||
return err | ||
} | ||
ttyIn.Close() | ||
ttyOut.Close() | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
// +build !windows | ||
//go:build !windows && !darwin | ||
|
||
package console | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
// +build windows | ||
//go:build windows | ||
|
||
package console | ||
|
||
|