Use golang.org/x/sys/windows in termstatus

Some functionality is missing, but at least the types are all defined.
Replaced short, word, dword by their Go names to match the x/sys
convention.
This commit is contained in:
greatroar 2020-02-29 17:22:38 +01:00
parent c8a672fa29
commit 7447c44484

View file

@ -8,6 +8,7 @@ import (
"unsafe" "unsafe"
"golang.org/x/crypto/ssh/terminal" "golang.org/x/crypto/ssh/terminal"
"golang.org/x/sys/windows"
) )
// clearCurrentLine removes all characters from the current line and resets the // clearCurrentLine removes all characters from the current line and resets the
@ -19,7 +20,7 @@ func clearCurrentLine(wr io.Writer, fd uintptr) func(io.Writer, uintptr) {
} }
// check if the output file type is a pipe (0x0003) // check if the output file type is a pipe (0x0003)
if getFileType(fd) != fileTypePipe { if isPipe(fd) {
// return empty func, update state is not possible on this terminal // return empty func, update state is not possible on this terminal
return func(io.Writer, uintptr) {} return func(io.Writer, uintptr) {}
} }
@ -36,7 +37,7 @@ func moveCursorUp(wr io.Writer, fd uintptr) func(io.Writer, uintptr, int) {
} }
// check if the output file type is a pipe (0x0003) // check if the output file type is a pipe (0x0003)
if getFileType(fd) != fileTypePipe { if isPipe(fd) {
// return empty func, update state is not possible on this terminal // return empty func, update state is not possible on this terminal
return func(io.Writer, uintptr, int) {} return func(io.Writer, uintptr, int) {}
} }
@ -48,63 +49,37 @@ func moveCursorUp(wr io.Writer, fd uintptr) func(io.Writer, uintptr, int) {
var kernel32 = syscall.NewLazyDLL("kernel32.dll") var kernel32 = syscall.NewLazyDLL("kernel32.dll")
var ( var (
procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
procSetConsoleCursorPosition = kernel32.NewProc("SetConsoleCursorPosition") procSetConsoleCursorPosition = kernel32.NewProc("SetConsoleCursorPosition")
procFillConsoleOutputCharacter = kernel32.NewProc("FillConsoleOutputCharacterW") procFillConsoleOutputCharacter = kernel32.NewProc("FillConsoleOutputCharacterW")
procFillConsoleOutputAttribute = kernel32.NewProc("FillConsoleOutputAttribute") procFillConsoleOutputAttribute = kernel32.NewProc("FillConsoleOutputAttribute")
procGetFileType = kernel32.NewProc("GetFileType")
)
type (
short int16
word uint16
dword uint32
coord struct {
x short
y short
}
smallRect struct {
left short
top short
right short
bottom short
}
consoleScreenBufferInfo struct {
size coord
cursorPosition coord
attributes word
window smallRect
maximumWindowSize coord
}
) )
// windowsClearCurrentLine removes all characters from the current line and // windowsClearCurrentLine removes all characters from the current line and
// resets the cursor position to the first column. // resets the cursor position to the first column.
func windowsClearCurrentLine(wr io.Writer, fd uintptr) { func windowsClearCurrentLine(wr io.Writer, fd uintptr) {
var info consoleScreenBufferInfo var info windows.ConsoleScreenBufferInfo
procGetConsoleScreenBufferInfo.Call(fd, uintptr(unsafe.Pointer(&info))) windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info)
// clear the line // clear the line
cursor := coord{ cursor := windows.Coord{
x: info.window.left, X: info.Window.Left,
y: info.cursorPosition.y, Y: info.CursorPosition.Y,
} }
var count, w dword var count, w uint32
count = dword(info.size.x) count = uint32(info.Size.X)
procFillConsoleOutputAttribute.Call(fd, uintptr(info.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&w))) procFillConsoleOutputAttribute.Call(fd, uintptr(info.Attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&w)))
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)))
} }
// windowsMoveCursorUp moves the cursor to the line n lines above the current one. // windowsMoveCursorUp moves the cursor to the line n lines above the current one.
func windowsMoveCursorUp(wr io.Writer, fd uintptr, n int) { func windowsMoveCursorUp(wr io.Writer, fd uintptr, n int) {
var info consoleScreenBufferInfo var info windows.ConsoleScreenBufferInfo
procGetConsoleScreenBufferInfo.Call(fd, uintptr(unsafe.Pointer(&info))) windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info)
// move cursor up by n lines and to the first column // move cursor up by n lines and to the first column
info.cursorPosition.y -= short(n) info.CursorPosition.Y -= int16(n)
info.cursorPosition.x = 0 info.CursorPosition.X = 0
procSetConsoleCursorPosition.Call(fd, uintptr(*(*int32)(unsafe.Pointer(&info.cursorPosition)))) procSetConsoleCursorPosition.Call(fd, uintptr(*(*int32)(unsafe.Pointer(&info.CursorPosition))))
} }
// isWindowsTerminal return true if the file descriptor is a windows terminal (cmd, psh). // isWindowsTerminal return true if the file descriptor is a windows terminal (cmd, psh).
@ -112,16 +87,9 @@ func isWindowsTerminal(fd uintptr) bool {
return terminal.IsTerminal(int(fd)) return terminal.IsTerminal(int(fd))
} }
const fileTypePipe = 0x0003 func isPipe(fd uintptr) bool {
typ, err := windows.GetFileType(windows.Handle(fd))
// getFileType returns the file type for the given fd. return err == nil && typ == windows.FILE_TYPE_PIPE
// https://msdn.microsoft.com/de-de/library/windows/desktop/aa364960(v=vs.85).aspx
func getFileType(fd uintptr) int {
r, _, e := syscall.Syscall(procGetFileType.Addr(), 1, fd, 0, 0)
if e != 0 {
return 0
}
return int(r)
} }
// canUpdateStatus returns true if status lines can be printed, the process // canUpdateStatus returns true if status lines can be printed, the process
@ -133,7 +101,7 @@ func canUpdateStatus(fd uintptr) bool {
} }
// check if the output file type is a pipe (0x0003) // check if the output file type is a pipe (0x0003)
if getFileType(fd) != fileTypePipe { if isPipe(fd) {
return false return false
} }