Use crypto/ssh/terminal instead of external stty command
This commit is contained in:
parent
2720816266
commit
03f5ef08c8
@ -11,6 +11,8 @@ import (
|
|||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/junegunn/fzf/src/util"
|
"github.com/junegunn/fzf/src/util"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/ssh/terminal"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -20,10 +22,12 @@ const (
|
|||||||
escPollInterval = 5
|
escPollInterval = 5
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const consoleDevice string = "/dev/tty"
|
||||||
|
|
||||||
func openTtyIn() *os.File {
|
func openTtyIn() *os.File {
|
||||||
in, err := os.OpenFile("/dev/tty", syscall.O_RDONLY, 0)
|
in, err := os.OpenFile(consoleDevice, syscall.O_RDONLY, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("Failed to open /dev/tty")
|
panic("Failed to open " + consoleDevice)
|
||||||
}
|
}
|
||||||
return in
|
return in
|
||||||
}
|
}
|
||||||
@ -64,7 +68,7 @@ type LightRenderer struct {
|
|||||||
clickY []int
|
clickY []int
|
||||||
ttyin *os.File
|
ttyin *os.File
|
||||||
buffer []byte
|
buffer []byte
|
||||||
ostty string
|
origState *terminal.State
|
||||||
width int
|
width int
|
||||||
height int
|
height int
|
||||||
yoffset int
|
yoffset int
|
||||||
@ -104,7 +108,14 @@ func NewLightRenderer(theme *ColorTheme, forceBlack bool, mouse bool, tabstop in
|
|||||||
return &r
|
return &r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *LightRenderer) fd() int {
|
||||||
|
return int(r.ttyin.Fd())
|
||||||
|
}
|
||||||
|
|
||||||
func (r *LightRenderer) defaultTheme() *ColorTheme {
|
func (r *LightRenderer) defaultTheme() *ColorTheme {
|
||||||
|
if strings.Contains(os.Getenv("TERM"), "256") {
|
||||||
|
return Dark256
|
||||||
|
}
|
||||||
colors, err := exec.Command("tput", "colors").Output()
|
colors, err := exec.Command("tput", "colors").Output()
|
||||||
if err == nil && atoi(strings.TrimSpace(string(colors)), 16) > 16 {
|
if err == nil && atoi(strings.TrimSpace(string(colors)), 16) > 16 {
|
||||||
return Dark256
|
return Dark256
|
||||||
@ -112,17 +123,6 @@ func (r *LightRenderer) defaultTheme() *ColorTheme {
|
|||||||
return Default16
|
return Default16
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *LightRenderer) stty(cmd string) string {
|
|
||||||
proc := exec.Command("stty", cmd)
|
|
||||||
proc.Stdin = r.ttyin
|
|
||||||
out, err := proc.Output()
|
|
||||||
if err != nil {
|
|
||||||
// Not sure how to handle this
|
|
||||||
panic("stty " + cmd + ": " + err.Error())
|
|
||||||
}
|
|
||||||
return strings.TrimSpace(string(out))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *LightRenderer) findOffset() (row int, col int) {
|
func (r *LightRenderer) findOffset() (row int, col int) {
|
||||||
r.csi("6n")
|
r.csi("6n")
|
||||||
r.flush()
|
r.flush()
|
||||||
@ -167,8 +167,13 @@ func (r *LightRenderer) Init() {
|
|||||||
}
|
}
|
||||||
r.escDelay = delay
|
r.escDelay = delay
|
||||||
|
|
||||||
r.ostty = r.stty("-g")
|
fd := r.fd()
|
||||||
r.stty("raw")
|
origState, err := terminal.GetState(fd)
|
||||||
|
if err != nil {
|
||||||
|
errorExit(err.Error())
|
||||||
|
}
|
||||||
|
r.origState = origState
|
||||||
|
terminal.MakeRaw(fd)
|
||||||
r.updateTerminalSize()
|
r.updateTerminalSize()
|
||||||
initTheme(r.theme, r.defaultTheme(), r.forceBlack)
|
initTheme(r.theme, r.defaultTheme(), r.forceBlack)
|
||||||
|
|
||||||
@ -212,14 +217,22 @@ func (r *LightRenderer) origin() {
|
|||||||
r.move(0, 0)
|
r.move(0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getEnv(name string, defaultValue int) int {
|
||||||
|
env := os.Getenv(name)
|
||||||
|
if len(env) == 0 {
|
||||||
|
return defaultValue
|
||||||
|
}
|
||||||
|
return atoi(env, defaultValue)
|
||||||
|
}
|
||||||
|
|
||||||
func (r *LightRenderer) updateTerminalSize() {
|
func (r *LightRenderer) updateTerminalSize() {
|
||||||
sizes := strings.Split(r.stty("size"), " ")
|
width, height, err := terminal.GetSize(r.fd())
|
||||||
if len(sizes) < 2 {
|
if err == nil {
|
||||||
r.width = defaultWidth
|
r.width = width
|
||||||
r.height = r.maxHeightFunc(defaultHeight)
|
r.height = r.maxHeightFunc(height)
|
||||||
} else {
|
} else {
|
||||||
r.width = atoi(sizes[1], defaultWidth)
|
r.width = getEnv("COLUMNS", defaultWidth)
|
||||||
r.height = r.maxHeightFunc(atoi(sizes[0], defaultHeight))
|
r.height = r.maxHeightFunc(getEnv("LINES", defaultHeight))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,7 +254,7 @@ func (r *LightRenderer) getBytesInternal(buffer []byte) []byte {
|
|||||||
c, ok := r.getch(false)
|
c, ok := r.getch(false)
|
||||||
if !ok {
|
if !ok {
|
||||||
r.Close()
|
r.Close()
|
||||||
errorExit("Failed to read /dev/tty")
|
errorExit("Failed to read " + consoleDevice)
|
||||||
}
|
}
|
||||||
|
|
||||||
retries := 0
|
retries := 0
|
||||||
@ -486,13 +499,13 @@ func (r *LightRenderer) mouseSequence(sz *int) Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *LightRenderer) Pause() {
|
func (r *LightRenderer) Pause() {
|
||||||
r.stty(r.ostty)
|
terminal.Restore(r.fd(), r.origState)
|
||||||
r.csi("?1049h")
|
r.csi("?1049h")
|
||||||
r.flush()
|
r.flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *LightRenderer) Resume() bool {
|
func (r *LightRenderer) Resume() bool {
|
||||||
r.stty("raw")
|
terminal.MakeRaw(r.fd())
|
||||||
r.csi("?1049l")
|
r.csi("?1049l")
|
||||||
r.flush()
|
r.flush()
|
||||||
// Should redraw
|
// Should redraw
|
||||||
@ -525,7 +538,7 @@ func (r *LightRenderer) Close() {
|
|||||||
r.csi("A")
|
r.csi("A")
|
||||||
}
|
}
|
||||||
r.flush()
|
r.flush()
|
||||||
r.stty(r.ostty)
|
terminal.Restore(r.fd(), r.origState)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *LightRenderer) MaxX() int {
|
func (r *LightRenderer) MaxX() int {
|
||||||
|
Loading…
Reference in New Issue
Block a user