New Upstream Snapshot - golang-github-buger-goterm

Ready changes

Summary

Merged new upstream version: 1.0.4+git20220522.1.0ebe063+ds (was: 0.0+git20181115.c206103).

Resulting package

Built on 2023-01-19T09:48 (took 5m25s)

The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:

apt install -t fresh-snapshots golang-github-buger-goterm-dev

Lintian Result

Diff

diff --git a/box.go b/box.go
index 7df929d..4a119c5 100644
--- a/box.go
+++ b/box.go
@@ -2,7 +2,9 @@ package goterm
 
 import (
 	"bytes"
+	"regexp"
 	"strings"
+	_ "unicode/utf8"
 )
 
 const DEFAULT_BORDER = "- │ ┌ ┐ └ ┘"
@@ -61,7 +63,9 @@ func (b *Box) Write(p []byte) (int, error) {
 	return b.Buf.Write(p)
 }
 
-// Render Box
+var ANSI_RE = regexp.MustCompile(`\\0\d+\[\d+(?:;\d+)?m`)
+
+// String renders Box
 func (b *Box) String() (out string) {
 	borders := strings.Split(b.Border, " ")
 	lines := strings.Split(b.Buf.String(), "\n")
@@ -74,7 +78,6 @@ func (b *Box) String() (out string) {
 
 	// Content width without borders and padding
 	contentWidth := b.Width - (b.PaddingX+1)*2
-
 	for y := 0; y < b.Height; y++ {
 		var line string
 
@@ -99,12 +102,63 @@ func (b *Box) String() (out string) {
 				line = ""
 			}
 
-			if len(line) > contentWidth-1 {
+			r := []rune(line)
+
+			lastAnsii := ""
+			withoutAnsii := []rune{}
+			withOffset := []rune{}
+			i := 0
+
+			for {
+				if i >= len(r) {
+					break
+				}
+
+				if r[i] == 27 {
+					lastAnsii = ""
+					withOffset = append(withOffset, r[i])
+					lastAnsii += string(r[i])
+					i++
+					for {
+
+						i++
+						if i > len(r) {
+							break
+						}
+
+						withOffset = append(withOffset, r[i])
+						lastAnsii += string(r[i])
+
+						if r[i] == 'm' {
+							i++
+							break
+						}
+					}
+				}
+
+				if i >= len(r) {
+					break
+				}
+
+				withoutAnsii = append(withoutAnsii, r[i])
+
+				if len(withoutAnsii) <= contentWidth {
+					withOffset = append(withOffset, r[i])
+				}
+
+				i++
+			}
+
+			if len(withoutAnsii) > contentWidth {
 				// If line is too large limit it
-				line = line[0:contentWidth]
+				line = string(withOffset)
 			} else {
 				// If line is too small enlarge it by adding spaces
-				line = line + strings.Repeat(" ", contentWidth-len(line))
+				line += strings.Repeat(" ", contentWidth-len(withoutAnsii))
+			}
+
+			if lastAnsii != "" {
+				line += RESET
 			}
 
 			line = prefix + line + suffix
@@ -112,7 +166,7 @@ func (b *Box) String() (out string) {
 
 		// Don't add newline for last element
 		if y != b.Height-1 {
-			line = line + "\n"
+			line += "\n"
 		}
 
 		out += line
diff --git a/box_test.go b/box_test.go
index 18cd8fc..c2ada46 100644
--- a/box_test.go
+++ b/box_test.go
@@ -14,7 +14,26 @@ func TestBox(t *testing.T) {
 └--------┘`
 
 	box := NewBox(10, 5, 0)
-	fmt.Fprint(box, "hello\nworld\ntest")
+	fmt.Fprint(box, "hello i'm very long string\nworld\ntest")
+
+	if box.String() != boxSample[1:] {
+		t.Error("\n" + box.String())
+		t.Error("!=")
+		t.Error(boxSample)
+		t.Error(len(box.String()), len(boxSample))
+	}
+}
+
+func TestBox_WithUnicode(t *testing.T) {
+	boxSample := `
+┌--------┐
+│ hell☺  │
+│ w©rld  │
+│ test✓✓ │
+└--------┘`
+
+	box := NewBox(10, 5, 0)
+	fmt.Fprint(box, "hell☺\nw©rld\ntest✓✓")
 
 	if box.String() != boxSample[1:] {
 		t.Error("\n" + box.String())
diff --git a/debian/changelog b/debian/changelog
index dbefb36..22f60ee 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+golang-github-buger-goterm (1.0.4+git20220522.1.0ebe063+ds-1) UNRELEASED; urgency=low
+
+  * New upstream snapshot.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Thu, 19 Jan 2023 09:45:01 -0000
+
 golang-github-buger-goterm (0.0+git20181115.c206103-3) unstable; urgency=medium
 
   [ Debian Janitor ]
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..47f0e68
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,5 @@
+module github.com/buger/goterm
+
+go 1.15
+
+require golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..a9c9b7f
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,2 @@
+golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54 h1:rF3Ohx8DRyl8h2zw9qojyLHLhrJpEMgyPOImREEryf0=
+golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
diff --git a/plot.go b/plot.go
index 1201476..504358c 100644
--- a/plot.go
+++ b/plot.go
@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"math"
 	"strings"
+	"unicode/utf8"
 )
 
 const (
@@ -119,7 +120,7 @@ func (c *LineChart) DrawAxes(maxX, minX, maxY, minY float64, index int) {
 	c.writeText(ff(minX), c.paddingX, 0)
 
 	x_col := c.data.columns[0]
-	c.writeText(c.data.columns[0], c.Width/2-len(x_col)/2, 1)
+	c.writeText(c.data.columns[0], c.Width/2-utf8.RuneCountInString(x_col)/2, 1)
 
 	if c.Flags&DRAW_INDEPENDENT != 0 || len(c.data.columns) < 3 {
 		col := c.data.columns[index]
diff --git a/plot_test.go b/plot_test.go
index fa0d63a..bdac81e 100644
--- a/plot_test.go
+++ b/plot_test.go
@@ -34,7 +34,7 @@ func TestCreateDataTable(t *testing.T) {
 }
 
 func TestLineChartIndependent(t *testing.T) {
-	fmt.Println("Independent charts\n")
+	fmt.Print("Independent charts\n\n")
 
 	chart := NewLineChart(100, 20)
 	chart.Flags = DRAW_INDEPENDENT //| DRAW_RELATIVE
@@ -51,7 +51,7 @@ func TestLineChartIndependent(t *testing.T) {
 	dataReversed.AddColumn("Lat")
 	dataReversed.AddColumn("Count")
 
-	//data.AddColumn("x*x")
+	// data.AddColumn("x*x")
 
 	for i := 0; i < 60; i++ {
 		x := float64(i + 60)
@@ -62,13 +62,13 @@ func TestLineChartIndependent(t *testing.T) {
 		dataReversed.AddRow(x, y2, y1)
 	}
 
-	// The two charts should look the same, only with inversed axes and colors
+	// The two charts should look the same, only with inverse axes and colors
 	fmt.Println(chart.Draw(data))
 	fmt.Println(chartReversed.Draw(dataReversed))
 }
 
 func TestLineChartRelative(t *testing.T) {
-	fmt.Println("Relative chart\n")
+	fmt.Print("Relative chart\n\n")
 
 	chart := NewLineChart(100, 20)
 	chart.Flags = DRAW_RELATIVE
@@ -78,7 +78,7 @@ func TestLineChartRelative(t *testing.T) {
 	data.AddColumn("Sin(x)")
 	data.AddColumn("Cos(x+1)")
 
-	//data.AddColumn("x*x")
+	// data.AddColumn("x*x")
 
 	for i := 0.1; i < 10; i += 0.1 {
 		data.AddRow(i, math.Sin(i), math.Cos(i+1))
@@ -88,10 +88,10 @@ func TestLineChartRelative(t *testing.T) {
 }
 
 func TestLineChart(t *testing.T) {
-	fmt.Println("Simple chart\n")
+	fmt.Print("Simple chart\n\n")
 
 	chart := NewLineChart(100, 20)
-	//chart.Flags = /*DRAW_INDEPENDENT // | */// DRAW_RELATIVE
+	// chart.Flags = /*DRAW_INDEPENDENT // | */// DRAW_RELATIVE
 
 	data := new(DataTable)
 	data.AddColumn("x")
diff --git a/terminal.go b/terminal.go
index 7c4dfa7..8631ccb 100644
--- a/terminal.go
+++ b/terminal.go
@@ -25,7 +25,7 @@ import (
 const RESET = "\033[0m"
 
 // Reset to default color
-const RESET_COLOR = "\033[32m"
+const RESET_COLOR = "\033[39;49m"
 
 // Return cursor to start of line and clean it
 const RESET_LINE = "\r\033[K"
@@ -44,14 +44,26 @@ const (
 
 var Output *bufio.Writer = bufio.NewWriter(os.Stdout)
 
-func getColor(code int) string {
+// Get ANSI escape code for given color code for foreground
+func GetColor(code int) string {
 	return fmt.Sprintf("\033[3%dm", code)
 }
 
-func getBgColor(code int) string {
+// Get ANSI escape code for given color code for background
+func GetBgColor(code int) string {
 	return fmt.Sprintf("\033[4%dm", code)
 }
 
+// Get ANSI escape code for given RGB color for foreground
+func GetColorRGB(r uint8, g uint8, b uint8) string {
+	return fmt.Sprintf("\033[38;2;%d;%d;%dm", r, g, b)
+}
+
+// Get ANSI escape code for given RGB color for background
+func GetBgColorRGB(r uint8, g uint8, b uint8) string {
+	return fmt.Sprintf("\033[48;2;%d;%d;%dm", r, g, b)
+}
+
 // Set percent flag: num | PCT
 //
 // Check percent flag: num & PCT
@@ -71,7 +83,7 @@ type winsize struct {
 // Its not recommended write to buffer dirrectly, use package Print,Printf,Println fucntions instead.
 var Screen *bytes.Buffer = new(bytes.Buffer)
 
-// Get relative or absolute coordinates
+// GetXY gets relative or absolute coordinates
 // To get relative, set PCT flag to number:
 //
 //      // Get 10% of total width to `x` and 20 to y
@@ -145,7 +157,7 @@ func MoveTo(str string, x int, y int) (out string) {
 	})
 }
 
-// Return carrier to start of line
+// ResetLine returns carrier to start of line
 func ResetLine(str string) (out string) {
 	return applyTransform(str, func(idx int, line string) string {
 		return fmt.Sprintf("%s%s", RESET_LINE, line)
@@ -165,7 +177,13 @@ func Bold(str string) string {
 //
 func Color(str string, color int) string {
 	return applyTransform(str, func(idx int, line string) string {
-		return fmt.Sprintf("%s%s%s", getColor(color), line, RESET)
+		return fmt.Sprintf("%s%s%s", GetColor(color), line, RESET)
+	})
+}
+
+func ColorRGB(str string, r uint8, g uint8, b uint8) string {
+	return applyTransform(str, func(idx int, line string) string {
+		return fmt.Sprintf("%s%s%s", GetColorRGB(r, g, b), line, RESET)
 	})
 }
 
@@ -184,11 +202,17 @@ func HighlightRegion(str string, from, to, color int) string {
 //
 func Background(str string, color int) string {
 	return applyTransform(str, func(idx int, line string) string {
-		return fmt.Sprintf("%s%s%s", getBgColor(color), line, RESET)
+		return fmt.Sprintf("%s%s%s", GetBgColor(color), line, RESET)
+	})
+}
+
+func BackgroundRGB(str string, r uint8, g uint8, b uint8) string {
+	return applyTransform(str, func(idx int, line string) string {
+		return fmt.Sprintf("%s%s%s", GetBgColorRGB(r, g, b), line, RESET)
 	})
 }
 
-// Get console width
+// Width gets console width
 func Width() int {
 	ws, err := getWinsize()
 
@@ -199,16 +223,7 @@ func Width() int {
 	return int(ws.Col)
 }
 
-// Get console height
-func Height() int {
-	ws, err := getWinsize()
-	if err != nil {
-		return -1
-	}
-	return int(ws.Row)
-}
-
-// Get current height. Line count in Screen buffer.
+// CurrentHeight gets current height. Line count in Screen buffer.
 func CurrentHeight() int {
 	return strings.Count(Screen.String(), "\n")
 }
diff --git a/terminal_nosysioctl.go b/terminal_nosysioctl.go
index 6906150..f4f4d5e 100644
--- a/terminal_nosysioctl.go
+++ b/terminal_nosysioctl.go
@@ -1,4 +1,5 @@
-// +build windows plan9 solaris
+//go:build plan9 || solaris
+// +build plan9 solaris
 
 package goterm
 
@@ -10,3 +11,12 @@ func getWinsize() (*winsize, error) {
 
 	return ws, nil
 }
+
+// Height gets console height
+func Height() int {
+	ws, err := getWinsize()
+	if err != nil {
+		return -1
+	}
+	return int(ws.Row)
+}
diff --git a/terminal_sysioctl.go b/terminal_sysioctl.go
index 5a61cd5..8b48b40 100644
--- a/terminal_sysioctl.go
+++ b/terminal_sysioctl.go
@@ -1,9 +1,13 @@
+//go:build !windows && !plan9 && !solaris
 // +build !windows,!plan9,!solaris
 
 package goterm
 
 import (
+	"errors"
+	"math"
 	"os"
+
 	"golang.org/x/sys/unix"
 )
 
@@ -16,3 +20,17 @@ func getWinsize() (*unix.Winsize, error) {
 
 	return ws, nil
 }
+
+// Height gets console height
+func Height() int {
+	ws, err := getWinsize()
+	if err != nil {
+		// returns math.MinInt32 if we could not retrieve the height of console window,
+		// like VSCode debugging console
+		if errors.Is(err, unix.EOPNOTSUPP) {
+			return math.MinInt32
+		}
+		return -1
+	}
+	return int(ws.Row)
+}
diff --git a/terminal_windows.go b/terminal_windows.go
new file mode 100644
index 0000000..e8236b6
--- /dev/null
+++ b/terminal_windows.go
@@ -0,0 +1,40 @@
+//go:build windows
+// +build windows
+
+package goterm
+
+import (
+	"errors"
+	"math"
+	"os"
+
+	"golang.org/x/sys/windows"
+)
+
+func getWinsize() (*winsize, error) {
+	ws := new(winsize)
+	fd := os.Stdout.Fd()
+	var info windows.ConsoleScreenBufferInfo
+	if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil {
+		return nil, err
+	}
+
+	ws.Col = uint16(info.Window.Right - info.Window.Left + 1)
+	ws.Row = uint16(info.Window.Bottom - info.Window.Top + 1)
+
+	return ws, nil
+}
+
+// Height gets console height
+func Height() int {
+	ws, err := getWinsize()
+	if err != nil {
+		// returns math.MinInt32 if we could not retrieve the height of console window,
+		// like VSCode debugging console
+		if errors.Is(err, windows.WSAEOPNOTSUPP) {
+			return math.MinInt32
+		}
+		return -1
+	}
+	return int(ws.Row)
+}

Debdiff

[The following lists of changes regard files as different if they have different names, permissions or owners.]

Files in second set of .debs but not in first

-rw-r--r--  root/root   /usr/share/gocode/src/github.com/buger/goterm/go.mod
-rw-r--r--  root/root   /usr/share/gocode/src/github.com/buger/goterm/go.sum
-rw-r--r--  root/root   /usr/share/gocode/src/github.com/buger/goterm/terminal_windows.go

No differences were encountered in the control files

More details

Full run details