diff --git a/cursor.go b/cursor.go index 5f07f5f..873b8ac 100644 --- a/cursor.go +++ b/cursor.go @@ -4,17 +4,27 @@ package cursor import ( "fmt" + "io" + "os" ) +var target io.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) { + target = w +} + // Up moves the cursor n lines up relative to the current position. func Up(n int) { - fmt.Printf("\x1b[%dA", n) + fmt.Fprintf(target, "\x1b[%dA", n) height += n } // Down moves the cursor n lines down relative to the current position. func Down(n int) { - fmt.Printf("\x1b[%dB", n) + fmt.Fprintf(target, "\x1b[%dB", n) if height-n <= 0 { height = 0 } else { @@ -24,36 +34,36 @@ func Down(n int) { // Right moves the cursor n characters to the right relative to the current position. func Right(n int) { - fmt.Printf("\x1b[%dC", n) + fmt.Fprintf(target, "\x1b[%dC", n) } // Left moves the cursor n characters to the left relative to the current position. func Left(n int) { - fmt.Printf("\x1b[%dD", n) + fmt.Fprintf(target, "\x1b[%dD", n) } // HorizontalAbsolute moves the cursor to n horizontally. // The position n is absolute to the start of the line. func HorizontalAbsolute(n int) { n += 1 // Moves the line to the character after n - fmt.Printf("\x1b[%dG", n) + fmt.Fprintf(target, "\x1b[%dG", n) } // Show the cursor if it was hidden previously. // 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 they reopen the terminal. func Show() { - fmt.Print("\x1b[?25h") + fmt.Fprint(target, "\x1b[?25h") } // Hide the cursor. // 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 they reopen the terminal. func Hide() { - fmt.Print("\x1b[?25l") + fmt.Fprintf(target, "\x1b[?25l") } // ClearLine clears the current line and moves the cursor to it's start position. func ClearLine() { - fmt.Print("\x1b[2K") + fmt.Fprintf(target, "\x1b[2K") } diff --git a/cursor_test.go b/cursor_test.go index b74902c..43c9f20 100644 --- a/cursor_test.go +++ b/cursor_test.go @@ -1,7 +1,9 @@ package cursor import ( + "bytes" "fmt" + "runtime" "testing" ) @@ -25,3 +27,75 @@ 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) + } +} diff --git a/cursor_windows.go b/cursor_windows.go index 35a5f77..79a9cf5 100644 --- a/cursor_windows.go +++ b/cursor_windows.go @@ -1,11 +1,17 @@ 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) { +} + // Up moves the cursor n lines up relative to the current position. func Up(n int) { move(0, -n)