forked from mirror/readline
add todo: support windows
This commit is contained in:
parent
593678baa5
commit
8dc3117d78
|
@ -19,6 +19,7 @@ You can read the source code in [example/main.go](https://github.com/chzyer/read
|
||||||
|
|
||||||
# Todo
|
# Todo
|
||||||
|
|
||||||
|
* Add support for windows
|
||||||
* Vim mode
|
* Vim mode
|
||||||
* More funny examples
|
* More funny examples
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/ssh/terminal"
|
"golang.org/x/crypto/ssh/terminal"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +25,7 @@ func NewTerminal(cfg *Config) (*Terminal, error) {
|
||||||
if err := cfg.Init(); err != nil {
|
if err := cfg.Init(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
state, err := MakeRaw(syscall.Stdin)
|
state, err := MakeRaw(StdinFd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -131,5 +130,5 @@ func (t *Terminal) Close() error {
|
||||||
}
|
}
|
||||||
t.stopChan <- struct{}{}
|
t.stopChan <- struct{}{}
|
||||||
t.wg.Wait()
|
t.wg.Wait()
|
||||||
return Restore(syscall.Stdin, t.state)
|
return Restore(StdinFd, t.state)
|
||||||
}
|
}
|
||||||
|
|
24
utils.go
24
utils.go
|
@ -1,9 +1,7 @@
|
||||||
package readline
|
package readline
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"syscall"
|
|
||||||
"unicode"
|
"unicode"
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/ssh/terminal"
|
"golang.org/x/crypto/ssh/terminal"
|
||||||
)
|
)
|
||||||
|
@ -67,28 +65,6 @@ func escapeKey(r rune) rune {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
type winsize struct {
|
|
||||||
Row uint16
|
|
||||||
Col uint16
|
|
||||||
Xpixel uint16
|
|
||||||
Ypixel uint16
|
|
||||||
}
|
|
||||||
|
|
||||||
// get width of the terminal
|
|
||||||
// we can cache it here and refresh after received signal
|
|
||||||
func getWidth() int {
|
|
||||||
ws := &winsize{}
|
|
||||||
retCode, _, errno := syscall.Syscall(syscall.SYS_IOCTL,
|
|
||||||
uintptr(syscall.Stdin),
|
|
||||||
uintptr(syscall.TIOCGWINSZ),
|
|
||||||
uintptr(unsafe.Pointer(ws)))
|
|
||||||
|
|
||||||
if int(retCode) == -1 {
|
|
||||||
panic(errno)
|
|
||||||
}
|
|
||||||
return int(ws.Col)
|
|
||||||
}
|
|
||||||
|
|
||||||
func RunesEqual(a, b []rune) bool {
|
func RunesEqual(a, b []rune) bool {
|
||||||
if len(a) != len(b) {
|
if len(a) != len(b) {
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
// +build darwin dragonfly freebsd linux,!appengine netbsd openbsd
|
||||||
|
|
||||||
|
package readline
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
StdinFd = syscall.Stdin
|
||||||
|
)
|
||||||
|
|
||||||
|
type winsize struct {
|
||||||
|
Row uint16
|
||||||
|
Col uint16
|
||||||
|
Xpixel uint16
|
||||||
|
Ypixel uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
// get width of the terminal
|
||||||
|
func getWidth() int {
|
||||||
|
ws := &winsize{}
|
||||||
|
retCode, _, errno := syscall.Syscall(syscall.SYS_IOCTL,
|
||||||
|
uintptr(StdinFd),
|
||||||
|
uintptr(syscall.TIOCGWINSZ),
|
||||||
|
uintptr(unsafe.Pointer(ws)))
|
||||||
|
|
||||||
|
if int(retCode) == -1 {
|
||||||
|
panic(errno)
|
||||||
|
}
|
||||||
|
return int(ws.Col)
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package readline
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
short int16
|
||||||
|
word uint16
|
||||||
|
|
||||||
|
small_rect struct {
|
||||||
|
left short
|
||||||
|
top short
|
||||||
|
right short
|
||||||
|
bottom short
|
||||||
|
}
|
||||||
|
|
||||||
|
coord struct {
|
||||||
|
x short
|
||||||
|
y short
|
||||||
|
}
|
||||||
|
|
||||||
|
console_screen_buffer_info struct {
|
||||||
|
size coord
|
||||||
|
cursor_position coord
|
||||||
|
attributes word
|
||||||
|
window small_rect
|
||||||
|
maximum_window_size coord
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
StdinFd = 0
|
||||||
|
kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||||
|
tmp_info console_screen_buffer_info
|
||||||
|
|
||||||
|
proc_get_console_screen_buffer_info = kernel32.NewProc("GetConsoleScreenBufferInfo")
|
||||||
|
)
|
||||||
|
|
||||||
|
func get_console_screen_buffer_info(h syscall.Handle, info *console_screen_buffer_info) (err error) {
|
||||||
|
r0, _, e1 := syscall.Syscall(proc_get_console_screen_buffer_info.Addr(),
|
||||||
|
2, uintptr(h), uintptr(unsafe.Pointer(info)), 0)
|
||||||
|
if int(r0) == 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
err = error(e1)
|
||||||
|
} else {
|
||||||
|
err = syscall.EINVAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func get_term_size(out syscall.Handle) coord {
|
||||||
|
err := get_console_screen_buffer_info(out, &tmp_info)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return tmp_info.size
|
||||||
|
}
|
||||||
|
|
||||||
|
// get width of the terminal
|
||||||
|
func getWidth() int {
|
||||||
|
return int(get_term_size(syscall.Stdin).x)
|
||||||
|
}
|
Loading…
Reference in New Issue