Skip to content

Commit

Permalink
Turn off terminal echo while progressbar is present.
Browse files Browse the repository at this point in the history
  • Loading branch information
mitchell-as committed Sep 20, 2023
1 parent 9583aeb commit 932b218
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 1 deletion.
7 changes: 6 additions & 1 deletion internal/output/progress.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type Spinner struct {
stop chan struct{}
interval time.Duration
reportedError bool
terminalState *terminalState
}

var _ Marshaller = &Spinner{}
Expand All @@ -28,7 +29,7 @@ func StartSpinner(out Outputer, msg string, interval time.Duration) *Spinner {
if out.Config().Interactive {
frames = []string{`|`, `/`, `-`, `\`}
}
d := &Spinner{0, frames, out, make(chan struct{}, 1), interval, false}
d := &Spinner{0, frames, out, make(chan struct{}, 1), interval, false, nil}

if msg != "" && d.out.Type() == PlainFormatName {
d.out.Fprint(d.out.Config().ErrWriter, strings.TrimSuffix(msg, " ")+" ")
Expand All @@ -39,6 +40,8 @@ func StartSpinner(out Outputer, msg string, interval time.Duration) *Spinner {
}()
}

d.turnOffEcho()

return d
}

Expand Down Expand Up @@ -110,6 +113,8 @@ func (d *Spinner) Stop(msg string) {
if d.out.Type() == PlainFormatName {
d.out.Fprint(d.out.Config().ErrWriter, "\n")
}

d.turnOnEcho()
}

func (d *Spinner) moveCaretBackInTerminal(n int) {
Expand Down
6 changes: 6 additions & 0 deletions internal/output/progress_darwin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package output

import "golang.org/x/sys/unix"

const ioctlReadTermios = unix.TIOCGETA
const ioctlWriteTermios = unix.TIOCSETA
6 changes: 6 additions & 0 deletions internal/output/progress_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package output

import "golang.org/x/sys/unix"

const ioctlReadTermios = unix.TCGETS
const ioctlWriteTermios = unix.TCSETS
37 changes: 37 additions & 0 deletions internal/output/progress_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,49 @@
package output

import (
"os"

"github.com/ActiveState/cli/internal/multilog"
"github.com/ActiveState/cli/internal/rollbar"
"golang.org/x/sys/unix"
)

type terminalState struct {
termios *unix.Termios
}

func (d *Spinner) moveCaretBackInCommandPrompt(n int) {
if !d.reportedError {
rollbar.Error("Incorrectly detected Windows command prompt in Unix environment")
d.reportedError = true
}
}

func (d *Spinner) turnOffEcho() {
fd := int(os.Stdin.Fd())
termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
if err != nil {
multilog.Error("Could not get termios: %v", err)
return
}

newState := *termios // copy
newState.Lflag &^= unix.ECHO
err = unix.IoctlSetTermios(fd, ioctlWriteTermios, &newState)
if err != nil {
multilog.Error("Could not set termios: %v", err)
return
}

d.terminalState = &terminalState{termios}
}

func (d *Spinner) turnOnEcho() {
if d.terminalState == nil {
return
}
err := unix.IoctlSetTermios(int(os.Stdin.Fd()), ioctlWriteTermios, d.terminalState.termios)
if err != nil {
multilog.Error("Could not restore termios: %v", err)
}
}
31 changes: 31 additions & 0 deletions internal/output/progress_win.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,34 @@ func (d *Spinner) moveCaretBackInCommandPrompt(n int) {
d.reportedError = true
}
}

type terminalState struct {
mode uint32
}

func (d *Spinner) turnOffEcho() {
var mode uint32
if err := windows.GetConsoleMode(windows.Handle(os.Stdin.Fd()), &mode); err != nil {
multilog.Error("Error calling GetConsoleMode: %v", err)
return
}

newMode := mode
newMode &^= windows.ENABLE_ECHO_INPUT
if err := windows.SetConsoleMode(windows.Handle(os.Stdin.Fd()), newMode); err != nil {
multilog.Error("Error calling SetConsoleMode: %v", err)
return
}

d.terminalState = &terminalState{mode}
}

func (d *Spinner) turnOnEcho() {
if d.terminalState == nil {
return
}
err := windows.SetConsoleMode(windows.Handle(os.Stdin.Fd()), d.terminalState.mode)
if err != nil {
multilog.Error("Error restoring mode via SetConsoleMode: %v", err)
}
}

0 comments on commit 932b218

Please sign in to comment.