readline/utils.go

186 lines
2.8 KiB
Go
Raw Normal View History

2015-09-20 18:14:29 +03:00
package readline
import (
2015-09-21 16:00:48 +03:00
"container/list"
2015-09-20 18:14:29 +03:00
"fmt"
"os"
2015-09-21 16:00:48 +03:00
"syscall"
2015-09-21 17:27:40 +03:00
"time"
2015-09-22 18:01:15 +03:00
"unicode/utf8"
2015-09-21 16:00:48 +03:00
"unsafe"
2015-09-20 18:14:29 +03:00
"golang.org/x/crypto/ssh/terminal"
)
// IsTerminal returns true if the given file descriptor is a terminal.
func IsTerminal(fd int) bool {
return terminal.IsTerminal(fd)
}
func MakeRaw(fd int) (*terminal.State, error) {
return terminal.MakeRaw(fd)
}
func Restore(fd int, state *terminal.State) error {
2015-09-24 19:16:49 +03:00
err := terminal.Restore(fd, state)
if err != nil {
if err.Error() == "errno 0" {
err = nil
}
}
return nil
2015-09-20 18:14:29 +03:00
}
func IsPrintable(key rune) bool {
isInSurrogateArea := key >= 0xd800 && key <= 0xdbff
return key >= 32 && !isInSurrogateArea
}
func escapeExKey(r rune) rune {
switch r {
case 'D':
r = CharBackward
case 'C':
r = CharForward
case 'A':
r = CharPrev
case 'B':
r = CharNext
}
return r
}
func escapeKey(r rune) rune {
2015-09-20 18:14:29 +03:00
switch r {
case 'b':
r = MetaPrev
case 'f':
r = MetaNext
case 'd':
r = MetaDelete
2015-09-23 08:03:13 +03:00
case CharTranspose:
r = MetaTranspose
2015-09-21 16:00:48 +03:00
case CharBackspace:
r = MetaBackspace
2015-09-23 06:46:56 +03:00
case CharEsc:
2015-09-21 08:13:30 +03:00
2015-09-20 18:14:29 +03:00
}
return r
}
func Debug(o ...interface{}) {
f, _ := os.OpenFile("debug.tmp", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
fmt.Fprintln(f, o...)
f.Close()
}
2015-09-21 16:00:48 +03:00
type winsize struct {
Row uint16
Col uint16
Xpixel uint16
Ypixel uint16
}
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 debugList(l *list.List) {
idx := 0
for e := l.Front(); e != nil; e = e.Next() {
Debug(idx, fmt.Sprintf("%+v", e.Value))
idx++
}
}
func equalRunes(a, b []rune) bool {
if len(a) != len(b) {
return false
}
for i := 0; i < len(a); i++ {
if a[i] != b[i] {
return false
}
}
return true
}
2015-09-21 17:27:40 +03:00
func sleep(n int) {
Debug(n)
time.Sleep(2000 * time.Millisecond)
}
2015-09-22 18:01:15 +03:00
func LineCount(w int) int {
screenWidth := getWidth()
r := w / screenWidth
if w%screenWidth != 0 {
r++
}
return r
}
func RunesWidth(r []rune) (length int) {
for i := 0; i < len(r); i++ {
2015-09-23 09:52:45 +03:00
if utf8.RuneLen(r[i]) > 3 {
2015-09-22 18:01:15 +03:00
length += 2
} else {
length += 1
}
}
return
}
2015-09-23 06:10:36 +03:00
func RunesIndexBck(r, sub []rune) int {
for i := len(r) - len(sub); i >= 0; i-- {
found := true
for j := 0; j < len(sub); j++ {
if r[i+j] != sub[j] {
found = false
break
}
}
if found {
return i
}
}
return -1
}
2015-09-22 18:01:15 +03:00
func RunesIndex(r, sub []rune) int {
for i := 0; i < len(r); i++ {
found := true
if len(r[i:]) < len(sub) {
return -1
}
for j := 0; j < len(sub); j++ {
if r[i+j] != sub[j] {
found = false
break
}
}
if found {
return i
}
}
return -1
}
2015-09-23 06:59:39 +03:00
func IsWordBreak(i rune) bool {
if i >= 'a' && i <= 'z' {
return false
}
if i >= 'A' && i <= 'Z' {
return false
}
return true
}