generated from atomicgo/template
-
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement cross-platform support
- Loading branch information
1 parent
93d678f
commit c9e4c6a
Showing
9 changed files
with
275 additions
and
232 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,110 +1,57 @@ | ||
// +build !windows | ||
|
||
package cursor | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
) | ||
|
||
const ( | ||
ansiPrefix = "\x1b[" | ||
|
||
upTemplate = "%dA" | ||
downTemplate = "%dB" | ||
leftTemplate = "%dD" | ||
rightTemplate = "%dC" | ||
|
||
nextLineTemplate = "%dE" | ||
previousLineTemplate = "%dF" | ||
|
||
positionTemplate = "%d;%dH" | ||
savePositionTemplate = "s" | ||
restorePositionTemplate = "u" | ||
|
||
openAlternativeScreenTemplate = "?1049h" | ||
closeAlternativeScreenTemplate = "?1049l" | ||
|
||
clearDisplayTemplate = "%dJ" | ||
clearLineTemplate = "%dK" | ||
|
||
showTemplate = "?25h" | ||
hideTemplate = "?25l" | ||
"path/filepath" | ||
) | ||
|
||
// Move cursor. | ||
|
||
// Up moves the cursor n cells up. If the cursor is already at the edge of the screen, this has no effect. | ||
// Up moves the cursor n lines up relative to the current position. | ||
func Up(n int) { | ||
fmt.Printf(ansiPrefix+upTemplate, n) | ||
fmt.Printf("\x1b[%dA", n) | ||
height += n | ||
} | ||
|
||
// Down moves the cursor n cells down. If the cursor is already at the edge of the screen, this has no effect. | ||
// Down moves the cursor n lines down relative to the current position. | ||
func Down(n int) { | ||
fmt.Printf(ansiPrefix+downTemplate, n) | ||
fmt.Printf("\x1b[%dB", n) | ||
height -= n | ||
} | ||
|
||
// Left moves the cursor n cells left. If the cursor is already at the edge of the screen, this has no effect. | ||
func Left(n int) { | ||
fmt.Printf(ansiPrefix+leftTemplate, n) | ||
} | ||
|
||
// Right moves the cursor n cells right. If the cursor is already at the edge of the screen, this has no effect. | ||
// Right moves the cursor n characters to the right relative to the current position. | ||
func Right(n int) { | ||
fmt.Printf(ansiPrefix+rightTemplate, n) | ||
fmt.Printf("\x1b[%dC", n) | ||
} | ||
|
||
// Move moves the cursor to a specific row and column. | ||
func Move(row int, column int) { | ||
fmt.Printf(ansiPrefix+positionTemplate, row, column) | ||
} | ||
|
||
func NextLine(n int) { | ||
fmt.Printf(ansiPrefix+nextLineTemplate, n) | ||
} | ||
|
||
func PrevLine(n int) { | ||
fmt.Printf(ansiPrefix+previousLineTemplate, n) | ||
} | ||
|
||
func SavePosition() { | ||
fmt.Print(ansiPrefix + savePositionTemplate) | ||
} | ||
|
||
func RestorePosition() { | ||
fmt.Print(ansiPrefix + restorePositionTemplate) | ||
// Left moves the cursor n characters to the left relative to the current position. | ||
func Left(n int) { | ||
fmt.Printf("\x1b[%dD", n) | ||
} | ||
|
||
// Alternative screen. | ||
|
||
func OpenAlternativeScreen() { | ||
fmt.Print(ansiPrefix + openAlternativeScreenTemplate) | ||
// 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) | ||
filepath.Base() | ||
} | ||
|
||
func CloseAlternativeScreen() { | ||
fmt.Print(ansiPrefix + closeAlternativeScreenTemplate) | ||
// Show the cursor if it was hidden previously. | ||
// Don't forget to show the cursor atleast 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() { | ||
fmt.Print("\x1b[?25h") | ||
} | ||
|
||
// Erase | ||
|
||
func ClearScreen() { | ||
fmt.Printf(ansiPrefix+clearDisplayTemplate, 2) | ||
Move(1, 1) | ||
// Hide the cursor. | ||
// Don't forget to show the cursor atleast 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() { | ||
fmt.Print("\x1b[?25l") | ||
} | ||
|
||
// ClearLine clears the current line and moves the cursor to it's start position. | ||
func ClearLine() { | ||
fmt.Printf(ansiPrefix+clearLineTemplate, 2) | ||
} | ||
|
||
func ClearLines(n int) { | ||
clear := fmt.Sprintf(ansiPrefix+clearLineTemplate, 2) | ||
fmt.Print(clear + strings.Repeat(fmt.Sprintf(ansiPrefix+upTemplate, 1)+clear, n)) | ||
} | ||
|
||
// Show and hide cursor | ||
|
||
func Show() { | ||
fmt.Printf(ansiPrefix + showTemplate) | ||
} | ||
|
||
func Hide() { | ||
fmt.Printf(ansiPrefix + hideTemplate) | ||
fmt.Print("\x1b[2K") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,144 +1,27 @@ | ||
package cursor | ||
|
||
import ( | ||
"io" | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/atomicgo/testutil" | ||
) | ||
|
||
func equal(t *testing.T, output string, input func(w io.Writer) error) { | ||
t.Helper() | ||
in, _ := testutil.CaptureStdout(input) | ||
if in != output { | ||
t.Errorf("Input: '%s' is not equal to '%s'", in, output) | ||
func TestHeightChanges(t *testing.T) { | ||
for i := 0; i < 4; i++ { | ||
fmt.Println() | ||
} | ||
Up(3) | ||
if height != 3 { | ||
t.Errorf("height should be 3 but is %d", height) | ||
} | ||
Down(3) | ||
if height != 0 { | ||
t.Errorf("height should be 0 but is %d", height) | ||
} | ||
} | ||
|
||
func TestClearLine(t *testing.T) { | ||
equal(t, "\x1b[2K", func(w io.Writer) error { | ||
ClearLine() | ||
|
||
return nil | ||
}) | ||
} | ||
|
||
func TestClearLines(t *testing.T) { | ||
equal(t, "\x1b[2K\x1b[1A\x1b[2K\x1b[1A\x1b[2K\x1b[1A\x1b[2K", func(w io.Writer) error { | ||
ClearLines(3) | ||
|
||
return nil | ||
}) | ||
} | ||
|
||
func TestClearScreen(t *testing.T) { | ||
equal(t, "\x1b[2J\x1b[1;1H", func(w io.Writer) error { | ||
ClearScreen() | ||
|
||
return nil | ||
}) | ||
} | ||
|
||
func TestCloseAlternativeScreen(t *testing.T) { | ||
equal(t, "\x1b[?1049l", func(w io.Writer) error { | ||
CloseAlternativeScreen() | ||
|
||
return nil | ||
}) | ||
} | ||
|
||
func TestDown(t *testing.T) { | ||
equal(t, "\x1b[6B", func(w io.Writer) error { | ||
Down(6) | ||
|
||
return nil | ||
}) | ||
} | ||
|
||
func TestHide(t *testing.T) { | ||
equal(t, "\x1b[?25l", func(w io.Writer) error { | ||
Hide() | ||
|
||
return nil | ||
}) | ||
} | ||
|
||
func TestLeft(t *testing.T) { | ||
equal(t, "\x1b[6D", func(w io.Writer) error { | ||
Left(6) | ||
|
||
return nil | ||
}) | ||
} | ||
|
||
func TestMove(t *testing.T) { | ||
equal(t, "\x1b[6;7H", func(w io.Writer) error { | ||
Move(6, 7) | ||
|
||
return nil | ||
}) | ||
} | ||
|
||
func TestNextLine(t *testing.T) { | ||
equal(t, "\x1b[6E", func(w io.Writer) error { | ||
NextLine(6) | ||
|
||
return nil | ||
}) | ||
} | ||
|
||
func TestOpenAlternativeScreen(t *testing.T) { | ||
equal(t, "\x1b[?1049h", func(w io.Writer) error { | ||
OpenAlternativeScreen() | ||
|
||
return nil | ||
}) | ||
} | ||
|
||
func TestPrevLine(t *testing.T) { | ||
equal(t, "\x1b[6F", func(w io.Writer) error { | ||
PrevLine(6) | ||
|
||
return nil | ||
}) | ||
} | ||
|
||
func TestRestorePosition(t *testing.T) { | ||
equal(t, "\x1b[u", func(w io.Writer) error { | ||
RestorePosition() | ||
|
||
return nil | ||
}) | ||
} | ||
|
||
func TestRight(t *testing.T) { | ||
equal(t, "\x1b[6C", func(w io.Writer) error { | ||
Right(6) | ||
|
||
return nil | ||
}) | ||
} | ||
|
||
func TestSavePosition(t *testing.T) { | ||
equal(t, "\x1b[s", func(w io.Writer) error { | ||
SavePosition() | ||
|
||
return nil | ||
}) | ||
} | ||
|
||
func TestShow(t *testing.T) { | ||
equal(t, "\x1b[?25h", func(w io.Writer) error { | ||
Show() | ||
|
||
return nil | ||
}) | ||
} | ||
|
||
func TestUp(t *testing.T) { | ||
equal(t, "\x1b[6A", func(w io.Writer) error { | ||
Up(6) | ||
|
||
return nil | ||
}) | ||
func TestHeightCannotBeNegative(t *testing.T) { | ||
Down(10) | ||
if height < 0 { | ||
t.Errorf("height is negative: %d", height) | ||
} | ||
} |
Oops, something went wrong.