finish windows support

This commit is contained in:
Cheney 2015-09-29 23:28:12 +08:00
parent 6eb29567f6
commit bb60b8a58f
9 changed files with 210 additions and 47 deletions

View File

@ -1,9 +1,10 @@
language: go language: go
go: go:
- 1.4
- 1.5 - 1.5
before_install: before_install:
- go get golang.org/x/crypto/ssh/terminal - go get golang.org/x/crypto/ssh/terminal
script: script:
- go install github.com/chzyer/readline/example - GOOS=windows go install github.com/chzyer/readline/example
- GOOS=linux go install github.com/chzyer/readline/example
- GOOS=darwin go install github.com/chzyer/readline/example
- go test -v - go test -v

View File

@ -12,9 +12,41 @@ import (
"unsafe" "unsafe"
) )
func init() { const (
Stdout = NewANSIWriter(Stdout) _ = uint16(0)
Stderr = NewANSIWriter(Stderr) COLOR_FBLUE = 0x0001
COLOR_FGREEN = 0x0002
COLOR_FRED = 0x0004
COLOR_FINTENSITY = 0x0008
COLOR_BBLUE = 0x0010
COLOR_BGREEN = 0x0020
COLOR_BRED = 0x0040
COLOR_BINTENSITY = 0x0080
COMMON_LVB_UNDERSCORE = 0x8000
)
var ColorTableFg = []word{
0, // 30: Black
COLOR_FRED, // 31: Red
COLOR_FGREEN, // 32: Green
COLOR_FRED | COLOR_FGREEN, // 33: Yellow
COLOR_FBLUE, // 34: Blue
COLOR_FRED | COLOR_FBLUE, // 35: Magenta
COLOR_FGREEN | COLOR_FBLUE, // 36: Cyan
COLOR_FRED | COLOR_FBLUE | COLOR_FGREEN, // 37: White
}
var ColorTableBg = []word{
0, // 40: Black
COLOR_BRED, // 41: Red
COLOR_BGREEN, // 42: Green
COLOR_BRED | COLOR_BGREEN, // 43: Yellow
COLOR_BBLUE, // 44: Blue
COLOR_BRED | COLOR_BBLUE, // 45: Magenta
COLOR_BGREEN | COLOR_BBLUE, // 46: Cyan
COLOR_BRED | COLOR_BBLUE | COLOR_BGREEN, // 47: White
} }
type ANSIWriter struct { type ANSIWriter struct {
@ -140,11 +172,13 @@ func (a *ANSIWriter) ioloopEscSeq(w *bufio.Writer, r rune, argptr *[]string) boo
break break
} }
if c >= 30 && c < 40 { if c >= 30 && c < 40 {
color ^= COLOR_FINTENSITY
color |= ColorTableFg[c-30] color |= ColorTableFg[c-30]
} else if c >= 40 && c < 50 { } else if c >= 40 && c < 50 {
color ^= COLOR_BINTENSITY
color |= ColorTableBg[c-40] color |= ColorTableBg[c-40]
} else if c == 4 { } else if c == 4 {
color |= COMMON_LVB_UNDERSCORE color |= COMMON_LVB_UNDERSCORE | ColorTableFg[7]
} else { // unknown code treat as reset } else { // unknown code treat as reset
color = ColorTableFg[7] color = ColorTableFg[7]
} }
@ -225,40 +259,3 @@ func eraseLine() error {
uintptr(unsafe.Pointer(&written)), uintptr(unsafe.Pointer(&written)),
) )
} }
const (
_ = uint16(0)
COLOR_FBLUE = 0x0001
COLOR_FGREEN = 0x0002
COLOR_FRED = 0x0004
COLOR_FINTENSITY = 0x0008
COLOR_BBLUE = 0x0010
COLOR_BGREEN = 0x0020
COLOR_BRED = 0x0040
COLOR_BINTENSITY = 0x0080
COMMON_LVB_UNDERSCORE = 0x8000
)
var ColorTableFg = []word{
0, // 30: Black
COLOR_FRED, // 31: Red
COLOR_FGREEN, // 32: Green
COLOR_FRED | COLOR_FGREEN, // 33: Yellow
COLOR_FBLUE, // 34: Blue
COLOR_FRED | COLOR_FBLUE, // 35: Magenta
COLOR_FGREEN | COLOR_FBLUE, // 36: Cyan
COLOR_FRED | COLOR_FBLUE | COLOR_FGREEN, // 37: White
}
var ColorTableBg = []word{
0, // 40: Black
COLOR_BRED, // 41: Red
COLOR_BGREEN, // 42: Green
COLOR_BRED | COLOR_BGREEN, // 43: Yellow
COLOR_BBLUE, // 44: Blue
COLOR_BRED | COLOR_BBLUE, // 45: Magenta
COLOR_BGREEN | COLOR_BBLUE, // 46: Cyan
COLOR_BRED | COLOR_BBLUE | COLOR_BGREEN, // 47: White
}

View File

@ -26,7 +26,7 @@ const (
) )
const ( const (
MetaPrev = -iota - 1 MetaPrev rune = -iota - 1
MetaNext MetaNext
MetaDelete MetaDelete
MetaBackspace MetaBackspace

View File

@ -7,6 +7,8 @@ import (
"strings" "strings"
"time" "time"
"gopkg.in/logex.v1"
"github.com/chzyer/readline" "github.com/chzyer/readline"
) )
@ -39,6 +41,7 @@ func main() {
HistoryFile: "/tmp/readline.tmp", HistoryFile: "/tmp/readline.tmp",
AutoComplete: completer, AutoComplete: completer,
}) })
logex.SetStd(logex.NewLoggerEx(l.Stderr()))
if err != nil { if err != nil {
panic(err) panic(err)
} }

122
rawreader_windows.go Normal file
View File

@ -0,0 +1,122 @@
// +build windows
package readline
import "unsafe"
const (
VK_CANCEL = 0x03
VK_BACK = 0x08
VK_TAB = 0x09
VK_RETURN = 0x0D
VK_SHIFT = 0x10
VK_CONTROL = 0x11
VK_MENU = 0x12
VK_ESCAPE = 0x1B
VK_LEFT = 0x25
VK_UP = 0x26
VK_RIGHT = 0x27
VK_DOWN = 0x28
VK_DELETE = 0x2E
VK_LSHIFT = 0xA0
VK_RSHIFT = 0xA1
VK_LCONTROL = 0xA2
VK_RCONTROL = 0xA3
)
type RawReader struct {
ctrlKey bool
altKey bool
}
func NewRawReader() *RawReader {
r := new(RawReader)
return r
}
func (r *RawReader) Read(buf []byte) (int, error) {
ir := new(_INPUT_RECORD)
var read int
var err error
next:
err = kernel.ReadConsoleInputW(stdin,
uintptr(unsafe.Pointer(ir)),
1,
uintptr(unsafe.Pointer(&read)),
)
if err != nil {
return 0, err
}
if ir.EventType != EVENT_KEY {
goto next
}
ker := (*_KEY_EVENT_RECORD)(unsafe.Pointer(&ir.Event[0]))
if ker.bKeyDown == 0 { // keyup
if r.ctrlKey || r.altKey {
switch ker.wVirtualKeyCode {
case VK_RCONTROL, VK_LCONTROL:
r.ctrlKey = false
case VK_MENU: //alt
r.altKey = false
}
}
goto next
}
if ker.unicodeChar == 0 {
var target rune
switch ker.wVirtualKeyCode {
case VK_RCONTROL, VK_LCONTROL:
r.ctrlKey = true
case VK_MENU: //alt
r.altKey = true
case VK_LEFT:
target = CharBackward
case VK_RIGHT:
target = CharForward
case VK_UP:
target = CharPrev
case VK_DOWN:
target = CharNext
}
if target != 0 {
return r.write(buf, target)
}
goto next
}
char := rune(ker.unicodeChar)
if r.ctrlKey {
switch char {
case 'A':
char = CharLineStart
case 'E':
char = CharLineEnd
case 'R':
char = CharBckSearch
case 'S':
char = CharFwdSearch
}
} else if r.altKey {
switch char {
case VK_BACK:
char = CharBackspace
}
return r.writeEsc(buf, char)
}
return r.write(buf, char)
}
func (r *RawReader) writeEsc(b []byte, char rune) (int, error) {
b[0] = '\033'
n := copy(b[1:], []byte(string(char)))
return n + 1, nil
}
func (r *RawReader) write(b []byte, char rune) (int, error) {
n := copy(b, []byte(string(char)))
return n, nil
}
func (r *RawReader) Close() error {
return nil
}

1
std.go
View File

@ -6,6 +6,7 @@ import (
) )
var ( var (
Stdin io.ReadCloser = os.Stdin
Stdout io.WriteCloser = os.Stdout Stdout io.WriteCloser = os.Stdout
Stderr io.WriteCloser = os.Stderr Stderr io.WriteCloser = os.Stderr
) )

9
std_windows.go Normal file
View File

@ -0,0 +1,9 @@
// +build windows
package readline
func init() {
Stdin = NewRawReader()
Stdout = NewANSIWriter(Stdout)
Stderr = NewANSIWriter(Stderr)
}

View File

@ -3,7 +3,6 @@ package readline
import ( import (
"bufio" "bufio"
"fmt" "fmt"
"os"
"sync" "sync"
"sync/atomic" "sync/atomic"
@ -81,7 +80,7 @@ func (t *Terminal) ioloop() {
expectNextChar bool expectNextChar bool
) )
buf := bufio.NewReader(os.Stdin) buf := bufio.NewReader(Stdin)
for { for {
if !expectNextChar { if !expectNextChar {
atomic.StoreInt64(&t.isReading, 0) atomic.StoreInt64(&t.isReading, 0)

View File

@ -11,14 +11,16 @@ import (
var ( var (
kernel = NewKernel() kernel = NewKernel()
stdout = uintptr(syscall.Stdout) stdout = uintptr(syscall.Stdout)
stdin = uintptr(syscall.Stdin)
) )
type Kernel struct { type Kernel struct {
SetConsoleCursorPosition, SetConsoleCursorPosition,
SetConsoleTextAttribute, SetConsoleTextAttribute,
GetConsoleScreenBufferInfo,
FillConsoleOutputCharacterW, FillConsoleOutputCharacterW,
FillConsoleOutputAttribute, FillConsoleOutputAttribute,
ReadConsoleInputW,
GetConsoleScreenBufferInfo,
GetConsoleCursorInfo, GetConsoleCursorInfo,
GetStdHandle CallFunc GetStdHandle CallFunc
} }
@ -26,6 +28,7 @@ type Kernel struct {
type short int16 type short int16
type word uint16 type word uint16
type dword uint32 type dword uint32
type wchar uint16
type _COORD struct { type _COORD struct {
x short x short
@ -36,6 +39,34 @@ func (c *_COORD) ptr() uintptr {
return uintptr(*(*int32)(unsafe.Pointer(c))) return uintptr(*(*int32)(unsafe.Pointer(c)))
} }
const (
EVENT_KEY = 0x0001
EVENT_MOUSE = 0x0002
EVENT_WINDOW_BUFFER_SIZE = 0x0004
EVENT_MENU = 0x0008
EVENT_FOCUS = 0x0010
)
type _KEY_EVENT_RECORD struct {
bKeyDown int32
wRepeatCount word
wVirtualKeyCode word
wVirtualScanCode word
unicodeChar wchar
dwControlKeyState dword
}
// KEY_EVENT_RECORD KeyEvent;
// MOUSE_EVENT_RECORD MouseEvent;
// WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
// MENU_EVENT_RECORD MenuEvent;
// FOCUS_EVENT_RECORD FocusEvent;
type _INPUT_RECORD struct {
EventType word
Padding uint16
Event [16]byte
}
type _CONSOLE_SCREEN_BUFFER_INFO struct { type _CONSOLE_SCREEN_BUFFER_INFO struct {
dwSize _COORD dwSize _COORD
dwCursorPosition _COORD dwCursorPosition _COORD