From 4504dcc85c4f0ed2828846539baefb505c8ea79f Mon Sep 17 00:00:00 2001 From: Ajitem Sahasrabuddhe Date: Fri, 12 Apr 2019 16:56:40 +0530 Subject: [PATCH 1/6] add support for get terminal size for windows --- terminal_size.go | 2 ++ terminal_size_windows.go | 64 ++++++++++++++++++++++++++++++++++++++++ writer_windows.go | 11 +++---- 3 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 terminal_size_windows.go diff --git a/terminal_size.go b/terminal_size.go index 3ae0132..a1b2634 100644 --- a/terminal_size.go +++ b/terminal_size.go @@ -1,3 +1,5 @@ +// +build !windows + package uilive import ( diff --git a/terminal_size_windows.go b/terminal_size_windows.go new file mode 100644 index 0000000..67d4b90 --- /dev/null +++ b/terminal_size_windows.go @@ -0,0 +1,64 @@ +// +build windows + +package uilive + +import ( + "math" + "os" + "syscall" + "unsafe" +) + +type consoleFontInfo struct { + font uint32 + fontSize coord +} + +const ( + SmCxMin = 28 + SmCyMin = 29 +) + +var ( + tmpConsoleFontInfo consoleFontInfo + moduleUser32 = syscall.NewLazyDLL("user32.dll") + procGetCurrentConsoleFont = kernel32.NewProc("GetCurrentConsoleFont") + getSystemMetrics = moduleUser32.NewProc("GetSystemMetrics") +) + +func getCurrentConsoleFont(h syscall.Handle, info *consoleFontInfo) (err error) { + r0, _, e1 := syscall.Syscall( + procGetCurrentConsoleFont.Addr(), 3, uintptr(h), 0, uintptr(unsafe.Pointer(info)), + ) + if int(r0) == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getTermSize() (int, int) { + out, err := syscall.Open("CONOUT$", syscall.O_RDWR, 0) + if err != nil { + os.Exit(1) + } + + x, _, err := getSystemMetrics.Call(SmCxMin) + y, _, err := getSystemMetrics.Call(SmCyMin) + + if x == 0 || y == 0 { + if err != nil { + panic(err) + } + } + + err1 := getCurrentConsoleFont(out, &tmpConsoleFontInfo) + if err1 != nil { + panic(err1) + } + + return int(math.Ceil(float64(x) / float64(tmpConsoleFontInfo.fontSize.x))), int(math.Ceil(float64(y) / float64(tmpConsoleFontInfo.fontSize.y))) +} diff --git a/writer_windows.go b/writer_windows.go index c7a0342..e696267 100644 --- a/writer_windows.go +++ b/writer_windows.go @@ -4,6 +4,8 @@ package uilive import ( "fmt" + "github.com/mattn/go-isatty" + "strings" "syscall" "unsafe" ) @@ -14,11 +16,10 @@ var ( procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo") procSetConsoleCursorPosition = kernel32.NewProc("SetConsoleCursorPosition") procFillConsoleOutputCharacter = kernel32.NewProc("FillConsoleOutputCharacterW") - procFillConsoleOutputAttribute = kernel32.NewProc("FillConsoleOutputAttribute") ) // clear the line and move the cursor up -var clear = fmt.Sprintf("%c[%dA%c[2K", ESC, 1, ESC) +var clear = fmt.Sprintf("%c[%dA%c[2K\r", ESC, 0, ESC) type short int16 type dword uint32 @@ -55,12 +56,12 @@ func (w *Writer) clearLines() { } fd := f.Fd() var csbi consoleScreenBufferInfo - procGetConsoleScreenBufferInfo.Call(fd, uintptr(unsafe.Pointer(&csbi))) + _, _, _ = procGetConsoleScreenBufferInfo.Call(fd, uintptr(unsafe.Pointer(&csbi))) for i := 0; i < w.lineCount; i++ { // move the cursor up csbi.cursorPosition.y-- - procSetConsoleCursorPosition.Call(fd, uintptr(*(*int32)(unsafe.Pointer(&csbi.cursorPosition)))) + _, _, _ = procSetConsoleCursorPosition.Call(fd, uintptr(*(*int32)(unsafe.Pointer(&csbi.cursorPosition)))) // clear the line cursor := coord{ x: csbi.window.left, @@ -68,6 +69,6 @@ func (w *Writer) clearLines() { } var count, w dword count = dword(csbi.size.x) - procFillConsoleOutputCharacter.Call(fd, uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&w))) + _, _, _ = procFillConsoleOutputCharacter.Call(fd, uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&w))) } } From 39b9ca9aa9139184aa2bc2dce873ed749b2d1aa5 Mon Sep 17 00:00:00 2001 From: Ajitem Sahasrabuddhe Date: Sat, 11 May 2019 22:24:39 +0530 Subject: [PATCH 2/6] return 0, 0 terminal size instead of calling os.Exit --- terminal_size.go | 4 ++-- terminal_size_windows.go | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/terminal_size.go b/terminal_size.go index a1b2634..c5f48b5 100644 --- a/terminal_size.go +++ b/terminal_size.go @@ -24,13 +24,13 @@ func getTermSize() (int, int) { if runtime.GOOS == "openbsd" { out, err = os.OpenFile("/dev/tty", os.O_RDWR, 0) if err != nil { - os.Exit(1) + return 0, 0 } } else { out, err = os.OpenFile("/dev/tty", os.O_WRONLY, 0) if err != nil { - os.Exit(1) + return 0, 0 } } _, _, _ = syscall.Syscall(syscall.SYS_IOCTL, diff --git a/terminal_size_windows.go b/terminal_size_windows.go index 67d4b90..71b8bec 100644 --- a/terminal_size_windows.go +++ b/terminal_size_windows.go @@ -4,7 +4,6 @@ package uilive import ( "math" - "os" "syscall" "unsafe" ) @@ -43,7 +42,7 @@ func getCurrentConsoleFont(h syscall.Handle, info *consoleFontInfo) (err error) func getTermSize() (int, int) { out, err := syscall.Open("CONOUT$", syscall.O_RDWR, 0) if err != nil { - os.Exit(1) + return 0, 0 } x, _, err := getSystemMetrics.Call(SmCxMin) @@ -55,9 +54,9 @@ func getTermSize() (int, int) { } } - err1 := getCurrentConsoleFont(out, &tmpConsoleFontInfo) - if err1 != nil { - panic(err1) + err = getCurrentConsoleFont(out, &tmpConsoleFontInfo) + if err != nil { + panic(err) } return int(math.Ceil(float64(x) / float64(tmpConsoleFontInfo.fontSize.x))), int(math.Ceil(float64(y) / float64(tmpConsoleFontInfo.fontSize.y))) From 76148ffd329a4962812033526113ad3431fc633d Mon Sep 17 00:00:00 2001 From: hoijui Date: Wed, 15 May 2019 15:45:32 +0200 Subject: [PATCH 3/6] use the termbox library to fetch terminal size [fix] #24 ... because it is platform agnostic -> works on windows too --- .travis.yml | 2 ++ terminal_size.go | 35 ++++++----------------------------- 2 files changed, 8 insertions(+), 29 deletions(-) diff --git a/.travis.yml b/.travis.yml index 04c834a..409eb04 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ language: go sudo: false +before_install: + - go get "github.com/nsf/termbox-go" install: - go get ./... go: diff --git a/terminal_size.go b/terminal_size.go index 3ae0132..a9d959d 100644 --- a/terminal_size.go +++ b/terminal_size.go @@ -1,37 +1,14 @@ package uilive import ( - "os" - "runtime" - "syscall" - "unsafe" + "github.com/nsf/termbox-go" ) -type windowSize struct { - rows uint16 - cols uint16 - xPixels uint16 - yPixels uint16 -} - -var out *os.File -var err error -var sz windowSize - func getTermSize() (int, int) { - if runtime.GOOS == "openbsd" { - out, err = os.OpenFile("/dev/tty", os.O_RDWR, 0) - if err != nil { - os.Exit(1) - } - - } else { - out, err = os.OpenFile("/dev/tty", os.O_WRONLY, 0) - if err != nil { - os.Exit(1) - } + if err := termbox.Init(); err != nil { + panic(err) } - _, _, _ = syscall.Syscall(syscall.SYS_IOCTL, - out.Fd(), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&sz))) - return int(sz.cols), int(sz.rows) + w, h := termbox.Size() + termbox.Close() + return w, h } From 1d3ec8b6ded1aa36f1eb6cda43e4587cfdc91818 Mon Sep 17 00:00:00 2001 From: hoijui Date: Wed, 15 May 2019 15:45:55 +0200 Subject: [PATCH 4/6] include missing windows imports [fix] #24 --- writer_windows.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/writer_windows.go b/writer_windows.go index c7a0342..d97a7c5 100644 --- a/writer_windows.go +++ b/writer_windows.go @@ -4,8 +4,10 @@ package uilive import ( "fmt" + "strings" "syscall" "unsafe" + "github.com/mattn/go-isatty" ) var kernel32 = syscall.NewLazyDLL("kernel32.dll") From 11a47eccca338528e16d13e2c70e550dfca9c75f Mon Sep 17 00:00:00 2001 From: hoijui Date: Wed, 15 May 2019 17:12:57 +0200 Subject: [PATCH 5/6] Travis-CI: add OSX and linux->win cross-compilation [fix] --- .travis.yml | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 409eb04..f5170df 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,27 @@ language: go sudo: false + +matrix: + include: + - go: 1.4 + os: linux + - go: tip + os: linux + env: CROSS_COMPILE=true + - go: tip + os: osx + before_install: - - go get "github.com/nsf/termbox-go" + - if [ "$CROSS_COMPILE" = "true" ]; then sudo apt update; fi + install: - - go get ./... -go: - - 1.4 - - tip + - if [ "$CROSS_COMPILE" = "true" ]; then sudo apt install libc6-dev-i386; fi + - if [ "$CROSS_COMPILE" = "true" ]; then sudo apt install gcc-mingw-w64; fi + - go get github.com/nsf/termbox-go + - if [ "$TRAVIS_OS_NAME" = "linux" -a "$CROSS_COMPILE" = "true" ]; then go get github.com/mattn/go-isatty ; fi + - go get -t -v ./... + +script: + - go build + - go test + - if [ "$TRAVIS_OS_NAME" = "linux" -a "$CROSS_COMPILE" = "true" ]; then env GOOS=windows GOARCH=amd64 CC=x86_64-w64-mingw32-gcc go build -v; fi From f2682d07cc70a09be1f5388737d20bcf696069c5 Mon Sep 17 00:00:00 2001 From: Ajitem Sahasrabuddhe Date: Thu, 16 May 2019 11:30:05 +0530 Subject: [PATCH 6/6] Use latest two supported versions of Go instead of tip. Disable CGO. --- .travis.yml | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index f5170df..345d805 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,25 +3,26 @@ sudo: false matrix: include: - - go: 1.4 + - go: 1.11.x os: linux - - go: tip + - go: 1.12.x + os: linux + - go: 1.11.x + os: linux + env: CROSS_COMPILE=true + - go: 1.12.x os: linux env: CROSS_COMPILE=true - - go: tip + - go: 1.11.x + os: osx + - go: 1.12.x os: osx - -before_install: - - if [ "$CROSS_COMPILE" = "true" ]; then sudo apt update; fi install: - - if [ "$CROSS_COMPILE" = "true" ]; then sudo apt install libc6-dev-i386; fi - - if [ "$CROSS_COMPILE" = "true" ]; then sudo apt install gcc-mingw-w64; fi - - go get github.com/nsf/termbox-go - if [ "$TRAVIS_OS_NAME" = "linux" -a "$CROSS_COMPILE" = "true" ]; then go get github.com/mattn/go-isatty ; fi - go get -t -v ./... script: - go build - go test - - if [ "$TRAVIS_OS_NAME" = "linux" -a "$CROSS_COMPILE" = "true" ]; then env GOOS=windows GOARCH=amd64 CC=x86_64-w64-mingw32-gcc go build -v; fi + - if [ "$TRAVIS_OS_NAME" = "linux" -a "$CROSS_COMPILE" = "true" ]; then env GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -v; fi