diff --git a/buffer.go b/buffer.go index 6b83501..352a9e8 100644 --- a/buffer.go +++ b/buffer.go @@ -1,12 +1,13 @@ package buf2d import ( + "fmt" "strings" ) // Buffer is a 2-dimensional rune buffer type Buffer struct { - data [][]rune + data [][]fmt.Stringer width int height int parent *Buffer @@ -14,11 +15,11 @@ type Buffer struct { // NewBuffer makes a new buffer with the given dimensions func NewBuffer(width, height int) *Buffer { - b := make([][]rune, height) + b := make([][]fmt.Stringer, height) for y := range b { - b[y] = make([]rune, width) + b[y] = make([]fmt.Stringer, width) for x := range b[y] { - b[y][x] = ' ' + b[y][x] = spaceStringer } } @@ -38,13 +39,18 @@ func (b *Buffer) y(y int) int { return limit(y, 0, b.height-1) } -// Set sets the rune at position (x,y) to c -func (b *Buffer) Set(x, y int, c rune) { +// Set sets the fmt.Stringer at position (x,y) to c +func (b *Buffer) Set(x, y int, c fmt.Stringer) { b.data[b.y(y)][b.x(x)] = c } -// Get returns the rune at position (x,y) -func (b *Buffer) Get(x, y int) rune { +// SetRune sets the fmt.Stringer at position (x,y) to rn +func (b *Buffer) SetRune(x, y int, rn rune) { + b.data[b.y(y)][b.x(x)] = newStringerFromRune(rn) +} + +// Get returns the fmt.Stringer at position (x,y) +func (b *Buffer) Get(x, y int) fmt.Stringer { return b.data[y][x] } @@ -63,11 +69,11 @@ func (b *Buffer) Height() int { return b.height } -// Draw calls drawFunc for every rune in this buffer -func (b *Buffer) Draw(drawFunc func(x, y int, c rune)) { +// ForEach calls f for every rune in this buffer +func (b *Buffer) ForEach(f func(x, y int, c fmt.Stringer)) { for y, col := range b.data { - for x, char := range col { - drawFunc(x, y, char) + for x, v := range col { + f(x, y, v) } } } @@ -75,8 +81,8 @@ func (b *Buffer) Draw(drawFunc func(x, y int, c rune)) { func (b *Buffer) String() string { s := new(strings.Builder) for ci, col := range b.data { - for _, char := range col { - s.WriteRune(char) + for _, v := range col { + s.WriteString(fmt.Sprintf("%v", v)) } if ci != len(b.data)-1 { s.WriteRune('\n') @@ -97,7 +103,7 @@ func (b *Buffer) Sub(x, y, w, h int) *Buffer { h = limit(h, 1, b.height-y) // make slice references - data := make([][]rune, h) + data := make([][]fmt.Stringer, h) for dy := 0; dy < h; dy++ { col := b.data[y+dy] data[dy] = col[x : x+w] diff --git a/buffer_test.go b/buffer_test.go index dea498f..f1e96aa 100644 --- a/buffer_test.go +++ b/buffer_test.go @@ -9,8 +9,8 @@ import ( func TestSub(t *testing.T) { b := NewBuffer(10, 10) s := b.Sub(1, 1, b.Width()-1, b.Height()-1) - b.Set(5, 1, 'a') - s.Set(5, 5, 'b') + b.SetRune(5, 1, 'a') + s.SetRune(5, 5, 'b') b.WriteString("Hello world", 1, 2) fmt.Println(b) diff --git a/utils.go b/utils.go index 0c3a776..7473b6c 100644 --- a/utils.go +++ b/utils.go @@ -1,5 +1,7 @@ package buf2d +import "fmt" + func limit(v, min, max int) int { return getmax(getmin(v, max), min) } @@ -17,3 +19,22 @@ func getmin(x, y int) int { } return y } + +type stringerImpl string + +func (s *stringerImpl) String() string { + return string(*s) +} + +func newStringer(str string) fmt.Stringer { + var impl stringerImpl = stringerImpl(str) + return &impl +} + +func newStringerFromRune(rn rune) fmt.Stringer { + return newStringer(string(rn)) +} + +var ( + spaceStringer = newStringer(" ") +) diff --git a/write_string.go b/write_string.go index dbacf9e..9df495c 100644 --- a/write_string.go +++ b/write_string.go @@ -1,6 +1,9 @@ package buf2d -import "strings" +import ( + "fmt" + "strings" +) // WriteString writes a whole string to the buffer at position (x,y) // no word wrap is applied at all. If the string does not fit, it will be truncated @@ -10,7 +13,7 @@ func (b *Buffer) WriteString(str string, x, y int) { if dx >= b.width { return } - b.Set(dx, y, r) + b.Set(dx, y, newStringerFromRune(r)) dx++ } } @@ -30,7 +33,7 @@ func (b *Buffer) WriteMultiLineString(str string, x, y int) { } // Fill fills the whole buffer with c -func (b *Buffer) Fill(c rune) { +func (b *Buffer) Fill(c fmt.Stringer) { for _, col := range b.data { for ri := range col { col[ri] = c