[cc'ing maintainer] Currently glab port doesn't properly handle terminal input, for example, after 'glab auth login' (setup wizard) you won't be able to type properly or choose the options, you will get ^[[B^[[A etc stuff.
This happens because survey library on which whole interface is based still uses syscall.* interface, which was removed in OpenBSD. The library (https://github.com/AlecAivazis/survey/) was abandoned by the author: > This project is no longer maintained. For an alternative, please check > out: https://github.com/charmbracelet/bubbletea Inlined patch for this library fixes everything for me, but I must admit that I've spent only couple hours with Go, and even if the patch looks simple it can contain stupid mistakes, I'd be appreciated if someone more proficient in Go can take a look at it (especially this 'unsafe' stuff). What would be the best way to bring the fix into the ports tree? To understand what I'm talking about here is the steps for reproduction: # build original gitlab-cli cd /tmp export GOPATH=/tmp/go git clone https://gitlab.com/gitlab-org/cli cd cli gmake ./bin/glab auth login <type/use arrows> reset # clone the library with the patch cd /tmp git clone https://github.com/bsdmp/survey # make go use patched library cd /tmp/cli go mod edit -replace github.com/AlecAivazis/survey/v2=/tmp/survey gmake ./bin/glab auth login <should work fine now> diff --git a/go.mod b/go.mod index 4837ce7..cc04509 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/mattn/go-isatty v0.0.8 github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b github.com/stretchr/testify v1.6.1 + golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 golang.org/x/text v0.4.0 ) diff --git a/terminal/runereader_posix.go b/terminal/runereader_posix.go index 563a081..4c1e88a 100644 --- a/terminal/runereader_posix.go +++ b/terminal/runereader_posix.go @@ -14,7 +14,7 @@ import ( "bytes" "fmt" "syscall" - "unsafe" + "golang.org/x/sys/unix" ) const ( @@ -23,7 +23,7 @@ const ( ) type runeReaderState struct { - term syscall.Termios + term unix.Termios reader *bufio.Reader buf *bytes.Buffer } @@ -45,19 +45,20 @@ func (rr *RuneReader) Buffer() *bytes.Buffer { // For reading runes we just want to disable echo. func (rr *RuneReader) SetTermMode() error { - if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(rr.stdio.In.Fd()), ioctlReadTermios, uintptr(unsafe.Pointer(&rr.state.term)), 0, 0, 0); err != 0 { + termios, err := unix.IoctlGetTermios((int)(rr.stdio.In.Fd()), ioctlReadTermios) + if err != nil { return err } - newState := rr.state.term - newState.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG + rr.state.term = *termios + termios.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG // Because we are clearing canonical mode, we need to ensure VMIN & VTIME are // set to the values we expect. This combination puts things in standard // "blocking read" mode (see termios(3)). - newState.Cc[syscall.VMIN] = 1 - newState.Cc[syscall.VTIME] = 0 + termios.Cc[syscall.VMIN] = 1 + termios.Cc[syscall.VTIME] = 0 - if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(rr.stdio.In.Fd()), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 { + if err = unix.IoctlSetTermios((int)(rr.stdio.In.Fd()), ioctlWriteTermios, termios); err != nil { return err } @@ -65,7 +66,7 @@ func (rr *RuneReader) SetTermMode() error { } func (rr *RuneReader) RestoreTermMode() error { - if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(rr.stdio.In.Fd()), ioctlWriteTermios, uintptr(unsafe.Pointer(&rr.state.term)), 0, 0, 0); err != 0 { + if err := unix.IoctlSetTermios((int)(rr.stdio.In.Fd()), ioctlWriteTermios, &rr.state.term); err != nil { return err } return nil