Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal to add windows support to the custom target functionality #8

Merged
merged 8 commits into from
Jun 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
coverage:
status:
project:
default:
informational: true
patch:
default:
informational: true
5 changes: 2 additions & 3 deletions cursor.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@ package cursor

import (
"fmt"
"io"
"os"
)

var target io.Writer = os.Stdout
var target Writer = os.Stdout

// SetTarget allows for any arbitrary io.Writer to be used
// for cursor movement (will not work on Windows).
func SetTarget(w io.Writer) {
func SetTarget(w Writer) {
target = w
}

Expand Down
74 changes: 0 additions & 74 deletions cursor_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package cursor

import (
"bytes"
"fmt"
"runtime"
"testing"
)

Expand All @@ -27,75 +25,3 @@ func TestHeightCannotBeNegative(t *testing.T) {
t.Errorf("height is negative: %d", height)
}
}

func TestCustomIOWriter(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("skipping these tests on windows")
}

var w bytes.Buffer
SetTarget(&w)

Up(2)
expected := "\x1b[2A"
actual := w.String()
if expected != actual {
t.Errorf("wanted: %v, got %v", expected, actual)
}

w.Reset()
Down(2)
expected = "\x1b[2B"
actual = w.String()
if expected != actual {
t.Errorf("wanted: %v, got %v", expected, actual)
}

w.Reset()
Right(2)
expected = "\x1b[2C"
actual = w.String()
if expected != actual {
t.Errorf("wanted: %v, got %v", expected, actual)
}

w.Reset()
Left(2)
expected = "\x1b[2D"
actual = w.String()
if expected != actual {
t.Errorf("wanted: %v, got %v", expected, actual)
}

w.Reset()
Hide()
expected = "\x1b[?25l"
actual = w.String()
if expected != actual {
t.Errorf("wanted: %v, got %v", expected, actual)
}

w.Reset()
Show()
expected = "\x1b[?25h"
actual = w.String()
if expected != actual {
t.Errorf("wanted: %v, got %v", expected, actual)
}

w.Reset()
ClearLine()
expected = "\x1b[2K"
actual = w.String()
if expected != actual {
t.Errorf("wanted: %v, got %v", expected, actual)
}

w.Reset()
HorizontalAbsolute(3)
expected = "\x1b[4G"
actual = w.String()
if expected != actual {
t.Errorf("wanted: %v, got %v", expected, actual)
}
}
109 changes: 109 additions & 0 deletions cursor_test_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package cursor

import (
"log"
"os"
"testing"
)

func TestCustomIOWriter(t *testing.T) {
tmpFile, err := os.CreateTemp("", "testingTmpFile-")
if err != nil {
log.Fatal(err)
}
defer os.Remove(tmpFile.Name())

w := tmpFile
SetTarget(w)

Up(2)
expected := "\x1b[2A"
actual := getFileContent(t, w.Name())
if expected != actual {
t.Errorf("wanted: %v, got %v", expected, actual)
}

clearFile(t, w)
Down(2)
expected = "\x1b[2B"
actual = getFileContent(t, w.Name())
if expected != actual {
t.Errorf("wanted: %v, got %v", expected, actual)
}

clearFile(t, w)
Right(2)
expected = "\x1b[2C"
actual = getFileContent(t, w.Name())
if expected != actual {
t.Errorf("wanted: %v, got %v", expected, actual)
}

clearFile(t, w)
Left(2)
expected = "\x1b[2D"
actual = getFileContent(t, w.Name())
if expected != actual {
t.Errorf("wanted: %v, got %v", expected, actual)
}

clearFile(t, w)
Hide()
expected = "\x1b[?25l"
actual = getFileContent(t, w.Name())
if expected != actual {
t.Errorf("wanted: %v, got %v", expected, actual)
}

clearFile(t, w)
Show()
expected = "\x1b[?25h"
actual = getFileContent(t, w.Name())
if expected != actual {
t.Errorf("wanted: %v, got %v", expected, actual)
}

clearFile(t, w)
ClearLine()
expected = "\x1b[2K"
actual = getFileContent(t, w.Name())
if expected != actual {
t.Errorf("wanted: %v, got %v", expected, actual)
}

clearFile(t, w)
HorizontalAbsolute(3)
expected = "\x1b[4G"
actual = getFileContent(t, w.Name())
if expected != actual {
t.Errorf("wanted: %v, got %v", expected, actual)
}
}

func getFileContent(t *testing.T, fileName string) string {
t.Helper()
content, err := os.ReadFile(fileName)
if err != nil {
t.Errorf("failed to read file contents: %s", err)

return ""
}

return string(content)
}

func clearFile(t *testing.T, file *os.File) {
t.Helper()
err := file.Truncate(0)
if err != nil {
t.Errorf("failed to clear file")

return
}
_, err = file.Seek(0, 0)
if err != nil {
t.Errorf("failed to clear file")

return
}
}
19 changes: 10 additions & 9 deletions cursor_windows.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package cursor

import (
"io"
"os"
"syscall"
"unsafe"
)

// SetTarget allows for any arbitrary io.Writer to be used
// for cursor movement (will not work on Windows).
func SetTarget(w io.Writer) {
var target Writer = os.Stdout

// SetTarget allows for any arbitrary Writer to be used
func SetTarget(w Writer) {
target = w
}

// Up moves the cursor n lines up relative to the current position.
Expand Down Expand Up @@ -39,7 +40,7 @@ func Left(n int) {
}

func move(x int, y int) {
handle := syscall.Handle(os.Stdout.Fd())
handle := syscall.Handle(target.Fd())

var csbi consoleScreenBufferInfo
_, _, _ = procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
Expand All @@ -54,7 +55,7 @@ func move(x int, y int) {
// HorizontalAbsolute moves the cursor to n horizontally.
// The position n is absolute to the start of the line.
func HorizontalAbsolute(n int) {
handle := syscall.Handle(os.Stdout.Fd())
handle := syscall.Handle(target.Fd())

var csbi consoleScreenBufferInfo
_, _, _ = procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
Expand All @@ -74,7 +75,7 @@ func HorizontalAbsolute(n int) {
// Don't forget to show the cursor at least at the end of your application.
// Otherwise the user might have a terminal with a permanently hidden cursor, until he reopens the terminal.
func Show() {
handle := syscall.Handle(os.Stdout.Fd())
handle := syscall.Handle(target.Fd())

var cci consoleCursorInfo
_, _, _ = procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&cci)))
Expand All @@ -87,7 +88,7 @@ func Show() {
// Don't forget to show the cursor at least at the end of your application with Show.
// Otherwise the user might have a terminal with a permanently hidden cursor, until he reopens the terminal.
func Hide() {
handle := syscall.Handle(os.Stdout.Fd())
handle := syscall.Handle(target.Fd())

var cci consoleCursorInfo
_, _, _ = procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&cci)))
Expand All @@ -98,7 +99,7 @@ func Hide() {

// ClearLine clears the current line and moves the cursor to it's start position.
func ClearLine() {
handle := syscall.Handle(os.Stdout.Fd())
handle := syscall.Handle(target.Fd())

var csbi consoleScreenBufferInfo
_, _, _ = procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
Expand Down
7 changes: 7 additions & 0 deletions utils.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package cursor

import "io"

var height int

// Bottom moves the cursor to the bottom of the terminal.
Expand Down Expand Up @@ -71,3 +73,8 @@ func ClearLinesDown(n int) {
DownAndClear(1)
}
}

type Writer interface {
io.Writer
Fd() uintptr
}