Skip to content

Commit ac1dd42

Browse files
committed
implement readPauseKey function for Unix and default platforms
1 parent 3ede518 commit ac1dd42

4 files changed

Lines changed: 99 additions & 5 deletions

File tree

jsh/lib/pretty/pretty.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,19 +128,18 @@ func PauseTerminal() bool {
128128
fmt.Fprintf(os.Stdout, ":")
129129
// switch stdin into 'raw' mode
130130
if oldState, err := term.MakeRaw(int(os.Stdin.Fd())); err == nil {
131-
var b []byte = make([]byte, 3)
132-
if _, err := os.Stdin.Read(b); err == nil {
133-
term.Restore(int(os.Stdin.Fd()), oldState)
131+
if key, err := readPauseKey(os.Stdin); err == nil {
132+
_ = term.Restore(int(os.Stdin.Fd()), oldState)
134133
// remove prompt, erase the current line
135134
fmt.Fprintf(os.Stdout, "\x1b[2K")
136135
// cursor backward
137136
fmt.Fprintf(os.Stdout, "\x1b[1D")
138-
if b[0] == 'q' || b[0] == 'Q' {
137+
if key == 'q' || key == 'Q' {
139138
return false
140139
}
141140
return true
142141
}
143-
term.Restore(int(os.Stdin.Fd()), oldState)
142+
_ = term.Restore(int(os.Stdin.Fd()), oldState)
144143
}
145144
return true
146145
}

jsh/lib/pretty/pretty_internal_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"math"
77
"os"
88
"path/filepath"
9+
"runtime"
910
"strings"
1011
"testing"
1112
"time"
@@ -105,6 +106,41 @@ func TestTerminalHelpersCoverage(t *testing.T) {
105106
}
106107
}
107108

109+
func TestReadPauseKeyDrainsBufferedInput(t *testing.T) {
110+
if runtime.GOOS == "windows" {
111+
t.Skip("buffered terminal input draining is Unix-specific")
112+
}
113+
114+
rIn, wIn, err := os.Pipe()
115+
if err != nil {
116+
t.Fatalf("os.Pipe() failed: %v", err)
117+
}
118+
defer rIn.Close()
119+
120+
if _, err := wIn.Write([]byte("\x1b[A")); err != nil {
121+
t.Fatalf("pipe write failed: %v", err)
122+
}
123+
124+
key, err := readPauseKey(rIn)
125+
if err != nil {
126+
t.Fatalf("readPauseKey() error = %v", err)
127+
}
128+
if key != '\x1b' {
129+
t.Fatalf("readPauseKey() = %q, want ESC", key)
130+
}
131+
132+
if err := wIn.Close(); err != nil {
133+
t.Fatalf("pipe close failed: %v", err)
134+
}
135+
remaining, err := io.ReadAll(rIn)
136+
if err != nil {
137+
t.Fatalf("pipe read failed: %v", err)
138+
}
139+
if len(remaining) != 0 {
140+
t.Fatalf("readPauseKey() left buffered input %q", string(remaining))
141+
}
142+
}
143+
108144
func TestFormattingHelpersCoverage(t *testing.T) {
109145
if got := Bytes(int64(2048)); got != "2.0KB" {
110146
t.Fatalf("Bytes() = %q", got)

jsh/lib/pretty/terminal_default.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//go:build !darwin && !linux && !freebsd && !openbsd && !netbsd
2+
3+
package pretty
4+
5+
import "os"
6+
7+
func readPauseKey(input *os.File) (byte, error) {
8+
buf := []byte{0}
9+
for {
10+
n, err := input.Read(buf)
11+
if err != nil {
12+
return 0, err
13+
}
14+
if n > 0 {
15+
return buf[0], nil
16+
}
17+
}
18+
}

jsh/lib/pretty/terminal_unix.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//go:build darwin || linux || freebsd || openbsd || netbsd
2+
3+
package pretty
4+
5+
import (
6+
"errors"
7+
"os"
8+
9+
"golang.org/x/sys/unix"
10+
)
11+
12+
func readPauseKey(input *os.File) (byte, error) {
13+
fd := int(input.Fd())
14+
buf := []byte{0}
15+
for {
16+
n, err := input.Read(buf)
17+
if err != nil {
18+
return 0, err
19+
}
20+
if n > 0 {
21+
break
22+
}
23+
}
24+
25+
drain := make([]byte, 32)
26+
for {
27+
pollFds := []unix.PollFd{{Fd: int32(fd), Events: unix.POLLIN}}
28+
ready, err := unix.Poll(pollFds, 10)
29+
if errors.Is(err, unix.EINTR) {
30+
continue
31+
}
32+
if err != nil || ready <= 0 || pollFds[0].Revents&unix.POLLIN == 0 {
33+
break
34+
}
35+
if n, err := input.Read(drain); err != nil || n == 0 {
36+
break
37+
}
38+
}
39+
40+
return buf[0], nil
41+
}

0 commit comments

Comments
 (0)