diff --git a/go.mod b/go.mod index 2e7516f..9c4c14f 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/charmbracelet/huh/spinner v0.0.0-20250714122654-40d2b68703eb github.com/charmbracelet/lipgloss v1.1.0 github.com/charmbracelet/log v0.4.2 - github.com/charmbracelet/x/term v0.2.1 + github.com/charmbracelet/x/term v0.2.2 github.com/denormal/go-gitignore v0.0.0-20180930084346-ae8ad1d07817 github.com/google/go-cmp v0.7.0 github.com/joho/godotenv v1.5.1 diff --git a/go.sum b/go.sum index 0b4b02a..935fcba 100644 --- a/go.sum +++ b/go.sum @@ -62,8 +62,8 @@ github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payR github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 h1:qko3AQ4gK1MTS/de7F5hPGx6/k1u0w4TeYmBFwzYVP4= github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0/go.mod h1:pBhA0ybfXv6hDjQUZ7hk1lVxBiUbupdw5R31yPUViVQ= -github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= -github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= +github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk= +github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8JawjaNZY= github.com/charmbracelet/x/termios v0.1.1/go.mod h1:rB7fnv1TgOPOyyKRJ9o+AsTU/vK5WHJ2ivHeut/Pcwo= github.com/charmbracelet/x/xpty v0.1.2 h1:Pqmu4TEJ8KeA9uSkISKMU3f+C1F6OGBn8ABuGlqCbtI= diff --git a/vendor/github.com/charmbracelet/x/term/term.go b/vendor/github.com/charmbracelet/x/term/term.go index 58d6522..151e475 100644 --- a/vendor/github.com/charmbracelet/x/term/term.go +++ b/vendor/github.com/charmbracelet/x/term/term.go @@ -1,3 +1,5 @@ +// Package term provides a platform-independent interfaces for interacting with +// Terminal and TTY devices. package term // State contains platform-specific state of a terminal. diff --git a/vendor/github.com/charmbracelet/x/term/term_plan9.go b/vendor/github.com/charmbracelet/x/term/term_plan9.go new file mode 100644 index 0000000..eba3bdf --- /dev/null +++ b/vendor/github.com/charmbracelet/x/term/term_plan9.go @@ -0,0 +1,118 @@ +package term + +import ( + "fmt" + "os" + "path/filepath" + "strings" +) + +type state struct { + termName string + raw bool + ctl *os.File +} + +// termName returns the name of the terminal or os.ErrNotExist if there is no terminal. +func termName(fd uintptr) (string, error) { + ctl, err := os.ReadFile(filepath.Join("/fd", fmt.Sprintf("%dctl", fd))) + if err != nil { + return "", err + } + f := strings.Fields(string(ctl)) + if len(f) == 0 { + return "", os.ErrNotExist + } + return f[len(f)-1], nil +} + +func isTerminal(fd uintptr) bool { + ctl, err := os.ReadFile(filepath.Join("/fd", fmt.Sprintf("%dctl", fd))) + if err != nil { + return false + } + if strings.Contains(string(ctl), "/dev/cons") { + return true + } + return false +} + +func makeRaw(fd uintptr) (*State, error) { + t, err := termName(fd) + if err != nil { + return nil, err + } + ctl, err := os.OpenFile(t, os.O_RDWR, 0) + if err != nil { + return nil, err + } + if _, err := ctl.Write([]byte("rawon")); err != nil { + return nil, err + } + return &State{state: state{termName: t, raw: true, ctl: ctl}}, nil +} + +func getState(fd uintptr) (*State, error) { + t, err := termName(fd) + if err != nil { + return nil, err + } + ctl, err := os.OpenFile(t, os.O_RDWR, 0) + if err != nil { + return nil, err + } + return &State{state: state{termName: t, raw: false, ctl: ctl}}, nil + +} + +func restore(_ uintptr, state *State) error { + if _, err := state.ctl.Write([]byte("rawoff")); err != nil { + return err + } + return nil +} + +// getSize returns the size. This will only work if you are running +// under a window manager in Plan 9. Else, the only option +// is to return a reasonable default. +func getSize(fd uintptr) (int, int, error) { + w, h := 80, 40 + b, err := os.ReadFile("/dev/wctl") + if err != nil { + return w, h, err + } + f := strings.Fields(string(b)) + if len(f) != 4 { + return w, h, fmt.Errorf("%q only has %d of 4 needed fields:%w", f, len(f), os.ErrInvalid) + } + // The contents of wctl, as defined in the driver, are + // 4 12-char fields: upper left x, y; and lower-right x, y + var ulx, uly, lrx, lry int + if n, err := fmt.Sscanf(string(b[:48]), "%d%d%d%d", &ulx, &uly, &lrx, &lry); n != 4 || err != nil { + return w, h, fmt.Errorf("scanning %q:%d of 4 items scanned:%w", string(b[:48]), n, err) + } + + w, h = lrx-lrx, lry-uly + return w, h, nil +} + +func setState(_ uintptr, state *State) error { + raw := "rawoff" + if state.raw { + raw = "rawon" + } + if _, err := state.ctl.Write([]byte(raw)); err != nil { + return err + } + return nil +} + +func readPassword(fd uintptr) ([]byte, error) { + f := os.NewFile(fd, "cons") + var b [128]byte + n, err := f.Read(b[:]) + if err != nil { + return nil, err + } + return b[:n], nil +} diff --git a/vendor/github.com/charmbracelet/x/term/term_unix.go b/vendor/github.com/charmbracelet/x/term/term_unix.go index 1459cb1..77706d4 100644 --- a/vendor/github.com/charmbracelet/x/term/term_unix.go +++ b/vendor/github.com/charmbracelet/x/term/term_unix.go @@ -19,7 +19,7 @@ func isTerminal(fd uintptr) bool { func makeRaw(fd uintptr) (*State, error) { termios, err := unix.IoctlGetTermios(int(fd), ioctlReadTermios) if err != nil { - return nil, err + return nil, err //nolint:wrapcheck } oldState := State{state{Termios: *termios}} @@ -34,7 +34,7 @@ func makeRaw(fd uintptr) (*State, error) { termios.Cc[unix.VMIN] = 1 termios.Cc[unix.VTIME] = 0 if err := unix.IoctlSetTermios(int(fd), ioctlWriteTermios, termios); err != nil { - return nil, err + return nil, err //nolint:wrapcheck } return &oldState, nil @@ -45,26 +45,26 @@ func setState(fd uintptr, state *State) error { if state != nil { termios = &state.Termios } - return unix.IoctlSetTermios(int(fd), ioctlWriteTermios, termios) + return unix.IoctlSetTermios(int(fd), ioctlWriteTermios, termios) //nolint:wrapcheck } func getState(fd uintptr) (*State, error) { termios, err := unix.IoctlGetTermios(int(fd), ioctlReadTermios) if err != nil { - return nil, err + return nil, err //nolint:wrapcheck } return &State{state{Termios: *termios}}, nil } func restore(fd uintptr, state *State) error { - return unix.IoctlSetTermios(int(fd), ioctlWriteTermios, &state.Termios) + return unix.IoctlSetTermios(int(fd), ioctlWriteTermios, &state.Termios) //nolint:wrapcheck } func getSize(fd uintptr) (width, height int, err error) { ws, err := unix.IoctlGetWinsize(int(fd), unix.TIOCGWINSZ) if err != nil { - return 0, 0, err + return 0, 0, err //nolint:wrapcheck } return int(ws.Col), int(ws.Row), nil } @@ -73,13 +73,13 @@ func getSize(fd uintptr) (width, height int, err error) { type passwordReader int func (r passwordReader) Read(buf []byte) (int, error) { - return unix.Read(int(r), buf) + return unix.Read(int(r), buf) //nolint:wrapcheck } func readPassword(fd uintptr) ([]byte, error) { termios, err := unix.IoctlGetTermios(int(fd), ioctlReadTermios) if err != nil { - return nil, err + return nil, err //nolint:wrapcheck } newState := *termios @@ -87,10 +87,10 @@ func readPassword(fd uintptr) ([]byte, error) { newState.Lflag |= unix.ICANON | unix.ISIG newState.Iflag |= unix.ICRNL if err := unix.IoctlSetTermios(int(fd), ioctlWriteTermios, &newState); err != nil { - return nil, err + return nil, err //nolint:wrapcheck } - defer unix.IoctlSetTermios(int(fd), ioctlWriteTermios, termios) + defer unix.IoctlSetTermios(int(fd), ioctlWriteTermios, termios) //nolint:errcheck return readPasswordLine(passwordReader(fd)) } diff --git a/vendor/github.com/charmbracelet/x/term/term_windows.go b/vendor/github.com/charmbracelet/x/term/term_windows.go index fe7afde..d94f684 100644 --- a/vendor/github.com/charmbracelet/x/term/term_windows.go +++ b/vendor/github.com/charmbracelet/x/term/term_windows.go @@ -24,7 +24,7 @@ func makeRaw(fd uintptr) (*State, error) { if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { return nil, err } - raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT) + raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT) raw |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil { return nil, err diff --git a/vendor/github.com/charmbracelet/x/term/util.go b/vendor/github.com/charmbracelet/x/term/util.go index b731341..9c2b628 100644 --- a/vendor/github.com/charmbracelet/x/term/util.go +++ b/vendor/github.com/charmbracelet/x/term/util.go @@ -41,7 +41,7 @@ func readPasswordLine(reader io.Reader) ([]byte, error) { if err == io.EOF && len(ret) > 0 { return ret, nil } - return ret, err + return ret, err //nolint:wrapcheck } } } diff --git a/vendor/modules.txt b/vendor/modules.txt index 236a23e..6d01b7c 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -131,8 +131,8 @@ github.com/charmbracelet/x/cellbuf # github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 ## explicit; go 1.19 github.com/charmbracelet/x/exp/strings -# github.com/charmbracelet/x/term v0.2.1 -## explicit; go 1.18 +# github.com/charmbracelet/x/term v0.2.2 +## explicit; go 1.24.0 github.com/charmbracelet/x/term # github.com/danieljoos/wincred v1.2.2 ## explicit; go 1.18