[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

Reply via email to