summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJunegunn Choi <junegunn.c@gmail.com>2017-01-15 13:10:59 +0900
committerJunegunn Choi <junegunn.c@gmail.com>2017-01-15 13:10:59 +0900
commit03f5ef08c8276f034269dbb8a6e6fd9decf58439 (patch)
tree3fb2e1d17a37efe317e8d675d22f97c190278baa
parent2720816266013793da99f75df4ab90fb3f4013c2 (diff)
Use crypto/ssh/terminal instead of external stty command
-rw-r--r--src/tui/light.go65
1 files changed, 39 insertions, 26 deletions
diff --git a/src/tui/light.go b/src/tui/light.go
index 0bfc57fd..2e99aa3f 100644
--- a/src/tui/light.go
+++ b/src/tui/light.go
@@ -11,6 +11,8 @@ import (
"unicode/utf8"
"github.com/junegunn/fzf/src/util"
+
+ "golang.org/x/crypto/ssh/terminal"
)
const (
@@ -20,10 +22,12 @@ const (
escPollInterval = 5
)
+const consoleDevice string = "/dev/tty"
+
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 {
- panic("Failed to open /dev/tty")
+ panic("Failed to open " + consoleDevice)
}
return in
}
@@ -64,7 +68,7 @@ type LightRenderer struct {
clickY []int
ttyin *os.File
buffer []byte
- ostty string
+ origState *terminal.State
width int
height int
yoffset int
@@ -104,7 +108,14 @@ func NewLightRenderer(theme *ColorTheme, forceBlack bool, mouse bool, tabstop in
return &r
}
+func (r *LightRenderer) fd() int {
+ return int(r.ttyin.Fd())
+}
+
func (r *LightRenderer) defaultTheme() *ColorTheme {
+ if strings.Contains(os.Getenv("TERM"), "256") {
+ return Dark256
+ }
colors, err := exec.Command("tput", "colors").Output()
if err == nil && atoi(strings.TrimSpace(string(colors)), 16) > 16 {
return Dark256
@@ -112,17 +123,6 @@ func (r *LightRenderer) defaultTheme() *ColorTheme {
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) {
r.csi("6n")
r.flush()
@@ -167,8 +167,13 @@ func (r *LightRenderer) Init() {
}
r.escDelay = delay
- r.ostty = r.stty("-g")
- r.stty("raw")
+ fd := r.fd()
+ origState, err := terminal.GetState(fd)
+ if err != nil {
+ errorExit(err.Error())
+ }
+ r.origState = origState
+ terminal.MakeRaw(fd)
r.updateTerminalSize()
initTheme(r.theme, r.defaultTheme(), r.forceBlack)
@@ -212,14 +217,22 @@ func (r *LightRenderer) origin() {
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() {
- sizes := strings.Split(r.stty("size"), " ")
- if len(sizes) < 2 {
- r.width = defaultWidth
- r.height = r.maxHeightFunc(defaultHeight)
+ width, height, err := terminal.GetSize(r.fd())
+ if err == nil {
+ r.width = width
+ r.height = r.maxHeightFunc(height)
} else {
- r.width = atoi(sizes[1], defaultWidth)
- r.height = r.maxHeightFunc(atoi(sizes[0], defaultHeight))
+ r.width = getEnv("COLUMNS", defaultWidth)
+ r.height = r.maxHeightFunc(getEnv("LINES", defaultHeight))
}
}
@@ -241,7 +254,7 @@ func (r *LightRenderer) getBytesInternal(buffer []byte) []byte {
c, ok := r.getch(false)
if !ok {
r.Close()
- errorExit("Failed to read /dev/tty")
+ errorExit("Failed to read " + consoleDevice)
}
retries := 0
@@ -486,13 +499,13 @@ func (r *LightRenderer) mouseSequence(sz *int) Event {
}
func (r *LightRenderer) Pause() {
- r.stty(r.ostty)
+ terminal.Restore(r.fd(), r.origState)
r.csi("?1049h")
r.flush()
}
func (r *LightRenderer) Resume() bool {
- r.stty("raw")
+ terminal.MakeRaw(r.fd())
r.csi("?1049l")
r.flush()
// Should redraw
@@ -525,7 +538,7 @@ func (r *LightRenderer) Close() {
r.csi("A")
}
r.flush()
- r.stty(r.ostty)
+ terminal.Restore(r.fd(), r.origState)
}
func (r *LightRenderer) MaxX() int {