Replace calls to `stty` with <termios.h> cgo
This removes the dependency on `stty` and is the standard POSIX way of modifying terminal state. It requires cgo, so cross-compiling might not be trivial. Otherwise there are no additional dependencies brought in, and this already supports all POSIXish platforms. Fixes #154.
This commit is contained in:
parent
36ae4a228f
commit
60c1c6cff4
20
client.go
20
client.go
|
@ -4,7 +4,6 @@ import (
|
|||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
@ -19,6 +18,7 @@ import (
|
|||
"tildegit.org/sloum/bombadillo/http"
|
||||
"tildegit.org/sloum/bombadillo/local"
|
||||
"tildegit.org/sloum/bombadillo/telnet"
|
||||
"tildegit.org/sloum/bombadillo/termios"
|
||||
)
|
||||
|
||||
//------------------------------------------------\\
|
||||
|
@ -43,14 +43,7 @@ type client struct {
|
|||
//--------------------------------------------------\\
|
||||
|
||||
func (c *client) GetSizeOnce() {
|
||||
cmd := exec.Command("stty", "size")
|
||||
cmd.Stdin = os.Stdin
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
cui.Exit(5, "Fatal error: Unable to retrieve terminal size")
|
||||
}
|
||||
var h, w int
|
||||
_, _ = fmt.Sscan(string(out), &h, &w)
|
||||
var w, h = termios.GetWindowSize()
|
||||
c.Height = h
|
||||
c.Width = w
|
||||
}
|
||||
|
@ -61,14 +54,7 @@ func (c *client) GetSize() {
|
|||
c.Draw()
|
||||
|
||||
for {
|
||||
cmd := exec.Command("stty", "size")
|
||||
cmd.Stdin = os.Stdin
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
cui.Exit(5, "Fatal error: Unable to retrieve terminal size")
|
||||
}
|
||||
var h, w int
|
||||
_, _ = fmt.Sscan(string(out), &h, &w)
|
||||
var w, h = termios.GetWindowSize()
|
||||
if h != c.Height || w != c.Width {
|
||||
c.Height = h
|
||||
c.Width = w
|
||||
|
|
32
cui/cui.go
32
cui/cui.go
|
@ -5,6 +5,8 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"tildegit.org/sloum/bombadillo/termios"
|
||||
)
|
||||
|
||||
var Shapes = map[string]string{
|
||||
|
@ -55,7 +57,7 @@ func Exit(exitCode int, msg string) {
|
|||
|
||||
// InitTerm sets the terminal modes appropriate for Bombadillo
|
||||
func InitTerm() {
|
||||
SetCharMode()
|
||||
termios.SetCharMode()
|
||||
Tput("smcup") // use alternate screen
|
||||
Tput("rmam") // turn off line wrapping
|
||||
}
|
||||
|
@ -64,7 +66,7 @@ func InitTerm() {
|
|||
func CleanupTerm() {
|
||||
moveCursorToward("down", 500)
|
||||
moveCursorToward("right", 500)
|
||||
SetLineMode()
|
||||
termios.SetLineMode()
|
||||
|
||||
fmt.Print("\n")
|
||||
fmt.Print("\033[?25h") // reenables cursor blinking
|
||||
|
@ -98,7 +100,7 @@ func Getch() rune {
|
|||
}
|
||||
|
||||
func GetLine(prefix string) (string, error) {
|
||||
SetLineMode()
|
||||
termios.SetLineMode()
|
||||
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
fmt.Print(prefix)
|
||||
|
@ -107,32 +109,10 @@ func GetLine(prefix string) (string, error) {
|
|||
return "", err
|
||||
}
|
||||
|
||||
SetCharMode()
|
||||
termios.SetCharMode()
|
||||
return text[:len(text)-1], nil
|
||||
}
|
||||
|
||||
func SetCharMode() {
|
||||
cmd := exec.Command("stty", "cbreak", "-echo")
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Print("\033[?25l")
|
||||
}
|
||||
|
||||
func SetLineMode() {
|
||||
cmd := exec.Command("stty", "-cbreak", "echo")
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Tput(opt string) {
|
||||
cmd := exec.Command("tput", opt)
|
||||
cmd.Stdin = os.Stdin
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
// +build cgo
|
||||
|
||||
package termios
|
||||
|
||||
/*
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <termios.h>
|
||||
// NOTE: ioctl() is variadic so cgo requires a wrapper
|
||||
int getWinsize(struct winsize* ws) {
|
||||
return ioctl(STDOUT_FILENO, TIOCGWINSZ, ws);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
func GetWindowSize() (int, int) {
|
||||
var value C.struct_winsize
|
||||
C.getWinsize(&value)
|
||||
return int(value.ws_col), int(value.ws_row)
|
||||
}
|
||||
|
||||
func getTermios() C.struct_termios {
|
||||
var termios C.struct_termios
|
||||
C.tcgetattr(C.STDIN_FILENO, &termios)
|
||||
return termios
|
||||
}
|
||||
|
||||
func setTermios(termios C.struct_termios) {
|
||||
C.tcsetattr(C.STDIN_FILENO, C.TCSAFLUSH, &termios)
|
||||
}
|
||||
|
||||
func SetCharMode() {
|
||||
var t = getTermios()
|
||||
t.c_lflag = t.c_lflag &^ (C.ICANON | C.ECHO)
|
||||
setTermios(t)
|
||||
}
|
||||
|
||||
func SetLineMode() {
|
||||
var t = getTermios()
|
||||
t.c_lflag = t.c_lflag | (C.ICANON | C.ECHO)
|
||||
setTermios(t)
|
||||
}
|
Loading…
Reference in New Issue