Merge pull request 'Replace calls to `stty` with syscalls' (#158) from dancek/bombadillo:replace-stty into release-2.3.0
This commit is contained in:
commit
cf340edc36
20
client.go
20
client.go
|
@ -4,7 +4,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -19,6 +18,7 @@ import (
|
||||||
"tildegit.org/sloum/bombadillo/http"
|
"tildegit.org/sloum/bombadillo/http"
|
||||||
"tildegit.org/sloum/bombadillo/local"
|
"tildegit.org/sloum/bombadillo/local"
|
||||||
"tildegit.org/sloum/bombadillo/telnet"
|
"tildegit.org/sloum/bombadillo/telnet"
|
||||||
|
"tildegit.org/sloum/bombadillo/termios"
|
||||||
)
|
)
|
||||||
|
|
||||||
//------------------------------------------------\\
|
//------------------------------------------------\\
|
||||||
|
@ -43,14 +43,7 @@ type client struct {
|
||||||
//--------------------------------------------------\\
|
//--------------------------------------------------\\
|
||||||
|
|
||||||
func (c *client) GetSizeOnce() {
|
func (c *client) GetSizeOnce() {
|
||||||
cmd := exec.Command("stty", "size")
|
var w, h = termios.GetWindowSize()
|
||||||
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)
|
|
||||||
c.Height = h
|
c.Height = h
|
||||||
c.Width = w
|
c.Width = w
|
||||||
}
|
}
|
||||||
|
@ -61,14 +54,7 @@ func (c *client) GetSize() {
|
||||||
c.Draw()
|
c.Draw()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
cmd := exec.Command("stty", "size")
|
var w, h = termios.GetWindowSize()
|
||||||
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)
|
|
||||||
if h != c.Height || w != c.Width {
|
if h != c.Height || w != c.Width {
|
||||||
c.Height = h
|
c.Height = h
|
||||||
c.Width = w
|
c.Width = w
|
||||||
|
|
37
cui/cui.go
37
cui/cui.go
|
@ -5,6 +5,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
|
"tildegit.org/sloum/bombadillo/termios"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Shapes = map[string]string{
|
var Shapes = map[string]string{
|
||||||
|
@ -55,16 +57,17 @@ func Exit(exitCode int, msg string) {
|
||||||
|
|
||||||
// InitTerm sets the terminal modes appropriate for Bombadillo
|
// InitTerm sets the terminal modes appropriate for Bombadillo
|
||||||
func InitTerm() {
|
func InitTerm() {
|
||||||
SetCharMode()
|
termios.SetCharMode()
|
||||||
Tput("smcup") // use alternate screen
|
Tput("smcup") // use alternate screen
|
||||||
Tput("rmam") // turn off line wrapping
|
Tput("rmam") // turn off line wrapping
|
||||||
|
fmt.Print("\033[?25l") // hide cursor
|
||||||
}
|
}
|
||||||
|
|
||||||
// CleanupTerm reverts changs to terminal mode made by InitTerm
|
// CleanupTerm reverts changs to terminal mode made by InitTerm
|
||||||
func CleanupTerm() {
|
func CleanupTerm() {
|
||||||
moveCursorToward("down", 500)
|
moveCursorToward("down", 500)
|
||||||
moveCursorToward("right", 500)
|
moveCursorToward("right", 500)
|
||||||
SetLineMode()
|
termios.SetLineMode()
|
||||||
|
|
||||||
fmt.Print("\n")
|
fmt.Print("\n")
|
||||||
fmt.Print("\033[?25h") // reenables cursor blinking
|
fmt.Print("\033[?25h") // reenables cursor blinking
|
||||||
|
@ -98,7 +101,7 @@ func Getch() rune {
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetLine(prefix string) (string, error) {
|
func GetLine(prefix string) (string, error) {
|
||||||
SetLineMode()
|
termios.SetLineMode()
|
||||||
|
|
||||||
reader := bufio.NewReader(os.Stdin)
|
reader := bufio.NewReader(os.Stdin)
|
||||||
fmt.Print(prefix)
|
fmt.Print(prefix)
|
||||||
|
@ -107,32 +110,10 @@ func GetLine(prefix string) (string, error) {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
SetCharMode()
|
termios.SetCharMode()
|
||||||
return text[:len(text)-1], nil
|
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) {
|
func Tput(opt string) {
|
||||||
cmd := exec.Command("tput", opt)
|
cmd := exec.Command("tput", opt)
|
||||||
cmd.Stdin = os.Stdin
|
cmd.Stdin = os.Stdin
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package termios
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
const (
|
||||||
|
getTermiosIoctl = syscall.TCGETS
|
||||||
|
setTermiosIoctl = syscall.TCSETS
|
||||||
|
)
|
|
@ -0,0 +1,10 @@
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
package termios
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
const (
|
||||||
|
getTermiosIoctl = syscall.TIOCGETA
|
||||||
|
setTermiosIoctl = syscall.TIOCSETAF
|
||||||
|
)
|
|
@ -0,0 +1,60 @@
|
||||||
|
package termios
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
type winsize struct {
|
||||||
|
Row uint16
|
||||||
|
Col uint16
|
||||||
|
Xpixel uint16
|
||||||
|
Ypixel uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
var fd = os.Stdin.Fd()
|
||||||
|
|
||||||
|
func ioctl(fd, request, argp uintptr) error {
|
||||||
|
if _, _, e := syscall.Syscall(syscall.SYS_IOCTL, fd, request, argp); e != 0 {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetWindowSize() (int, int) {
|
||||||
|
var value winsize
|
||||||
|
ioctl(fd, syscall.TIOCGWINSZ, uintptr(unsafe.Pointer(&value)))
|
||||||
|
return int(value.Col), int(value.Row)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTermios() syscall.Termios {
|
||||||
|
var value syscall.Termios
|
||||||
|
err := ioctl(fd, getTermiosIoctl, uintptr(unsafe.Pointer(&value)))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
func setTermios(termios syscall.Termios) {
|
||||||
|
err := ioctl(fd, setTermiosIoctl, uintptr(unsafe.Pointer(&termios)))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
runtime.KeepAlive(termios)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetCharMode() {
|
||||||
|
t := getTermios()
|
||||||
|
t.Lflag = t.Lflag ^ syscall.ICANON
|
||||||
|
t.Lflag = t.Lflag ^ syscall.ECHO
|
||||||
|
setTermios(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetLineMode() {
|
||||||
|
var t = getTermios()
|
||||||
|
t.Lflag = t.Lflag | (syscall.ICANON | syscall.ECHO)
|
||||||
|
setTermios(t)
|
||||||
|
}
|
Loading…
Reference in New Issue