mirror of
https://github.com/mum4k/termdash.git
synced 2025-04-25 13:48:50 +08:00
Adding canvas methods that can set cell options.
This commit is contained in:
parent
952242fb51
commit
2a817f9dbe
@ -16,7 +16,6 @@
|
||||
package canvas
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"image"
|
||||
|
||||
@ -100,13 +99,39 @@ func (c *Canvas) Cell(p image.Point) (*cell.Cell, error) {
|
||||
// Sets the default cell options if no options are provided.
|
||||
// This method is idempotent.
|
||||
func (c *Canvas) SetCellOpts(p image.Point, opts ...cell.Option) error {
|
||||
return errors.New("unimplemented")
|
||||
curCell, err := c.Cell(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(opts) == 0 {
|
||||
// Set the default options.
|
||||
opts = []cell.Option{
|
||||
cell.FgColor(cell.ColorDefault),
|
||||
cell.BgColor(cell.ColorDefault),
|
||||
}
|
||||
}
|
||||
if _, err := c.SetCell(p, curCell.Rune, opts...); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetAreaCellOpts is like SetCellOpts, but sets the specified options on all
|
||||
// the cells within the provided area.
|
||||
func (c *Canvas) SetAreaCellOpts(cellArea image.Rectangle, opts ...cell.Option) error {
|
||||
return errors.New("unimplemented")
|
||||
haveArea := c.Area()
|
||||
if !cellArea.In(haveArea) {
|
||||
return fmt.Errorf("unable to set cell options in area %v, it must fit inside the available cell area is %v", cellArea, haveArea)
|
||||
}
|
||||
for col := cellArea.Min.X; col < cellArea.Max.X; col++ {
|
||||
for row := cellArea.Min.Y; row < cellArea.Max.Y; row++ {
|
||||
if err := c.SetCellOpts(image.Point{col, row}, opts...); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// setCellFunc is a function that sets cell content on a terminal or a canvas.
|
||||
|
@ -100,6 +100,278 @@ func TestNew(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCanvas(t *testing.T) {
|
||||
tests := []struct {
|
||||
desc string
|
||||
canvas image.Rectangle
|
||||
ops func(*Canvas) error
|
||||
want func(size image.Point) (*faketerm.Terminal, error)
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
desc: "SetCellOpts fails on a point outside of the canvas",
|
||||
canvas: image.Rect(0, 0, 1, 1),
|
||||
ops: func(cvs *Canvas) error {
|
||||
return cvs.SetCellOpts(image.Point{1, 1})
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
desc: "SetCellOpts sets options on a cell with no options",
|
||||
canvas: image.Rect(0, 0, 2, 2),
|
||||
ops: func(cvs *Canvas) error {
|
||||
return cvs.SetCellOpts(image.Point{0, 1}, cell.FgColor(cell.ColorRed), cell.BgColor(cell.ColorBlue))
|
||||
},
|
||||
want: func(size image.Point) (*faketerm.Terminal, error) {
|
||||
ft := faketerm.MustNew(size)
|
||||
cvs, err := New(ft.Area())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c, err := cvs.Cell(image.Point{0, 1})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := cvs.SetCell(image.Point{0, 1}, c.Rune, cell.FgColor(cell.ColorRed), cell.BgColor(cell.ColorBlue)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := cvs.Apply(ft); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ft, nil
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "SetCellOpts preserves cell rune",
|
||||
canvas: image.Rect(0, 0, 2, 2),
|
||||
ops: func(cvs *Canvas) error {
|
||||
if _, err := cvs.SetCell(image.Point{0, 1}, 'X'); err != nil {
|
||||
return err
|
||||
}
|
||||
return cvs.SetCellOpts(image.Point{0, 1}, cell.FgColor(cell.ColorRed), cell.BgColor(cell.ColorBlue))
|
||||
},
|
||||
want: func(size image.Point) (*faketerm.Terminal, error) {
|
||||
ft := faketerm.MustNew(size)
|
||||
cvs, err := New(ft.Area())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err := cvs.SetCell(image.Point{0, 1}, 'X', cell.FgColor(cell.ColorRed), cell.BgColor(cell.ColorBlue)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := cvs.Apply(ft); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ft, nil
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "SetCellOpts overwrites options set previously",
|
||||
canvas: image.Rect(0, 0, 2, 2),
|
||||
ops: func(cvs *Canvas) error {
|
||||
if _, err := cvs.SetCell(image.Point{0, 1}, 'X', cell.FgColor(cell.ColorRed), cell.BgColor(cell.ColorBlue)); err != nil {
|
||||
return err
|
||||
}
|
||||
return cvs.SetCellOpts(image.Point{0, 1}, cell.FgColor(cell.ColorGreen), cell.BgColor(cell.ColorYellow))
|
||||
},
|
||||
want: func(size image.Point) (*faketerm.Terminal, error) {
|
||||
ft := faketerm.MustNew(size)
|
||||
cvs, err := New(ft.Area())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err := cvs.SetCell(image.Point{0, 1}, 'X', cell.FgColor(cell.ColorGreen), cell.BgColor(cell.ColorYellow)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := cvs.Apply(ft); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ft, nil
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "SetCellOpts sets default options when no options provided",
|
||||
canvas: image.Rect(0, 0, 2, 2),
|
||||
ops: func(cvs *Canvas) error {
|
||||
if _, err := cvs.SetCell(image.Point{0, 1}, 'X', cell.FgColor(cell.ColorRed), cell.BgColor(cell.ColorBlue)); err != nil {
|
||||
return err
|
||||
}
|
||||
return cvs.SetCellOpts(image.Point{0, 1})
|
||||
},
|
||||
want: func(size image.Point) (*faketerm.Terminal, error) {
|
||||
ft := faketerm.MustNew(size)
|
||||
cvs, err := New(ft.Area())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err := cvs.SetCell(image.Point{0, 1}, 'X'); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := cvs.Apply(ft); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ft, nil
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "SetCellOpts is idempotent",
|
||||
canvas: image.Rect(0, 0, 2, 2),
|
||||
ops: func(cvs *Canvas) error {
|
||||
if _, err := cvs.SetCell(image.Point{0, 1}, 'X'); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cvs.SetCellOpts(image.Point{0, 1}, cell.FgColor(cell.ColorRed), cell.BgColor(cell.ColorBlue)); err != nil {
|
||||
return err
|
||||
}
|
||||
return cvs.SetCellOpts(image.Point{0, 1}, cell.FgColor(cell.ColorRed), cell.BgColor(cell.ColorBlue))
|
||||
},
|
||||
want: func(size image.Point) (*faketerm.Terminal, error) {
|
||||
ft := faketerm.MustNew(size)
|
||||
cvs, err := New(ft.Area())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err := cvs.SetCell(image.Point{0, 1}, 'X', cell.FgColor(cell.ColorRed), cell.BgColor(cell.ColorBlue)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := cvs.Apply(ft); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ft, nil
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "SetAreaCellOpts fails on area too large",
|
||||
canvas: image.Rect(0, 0, 1, 1),
|
||||
ops: func(cvs *Canvas) error {
|
||||
return cvs.SetAreaCellOpts(image.Rect(0, 0, 2, 2), cell.FgColor(cell.ColorRed), cell.BgColor(cell.ColorBlue))
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
desc: "SetAreaCellOpts sets options in the full canvas",
|
||||
canvas: image.Rect(0, 0, 1, 1),
|
||||
ops: func(cvs *Canvas) error {
|
||||
return cvs.SetAreaCellOpts(image.Rect(0, 0, 1, 1), cell.FgColor(cell.ColorRed), cell.BgColor(cell.ColorBlue))
|
||||
},
|
||||
want: func(size image.Point) (*faketerm.Terminal, error) {
|
||||
ft := faketerm.MustNew(size)
|
||||
cvs, err := New(ft.Area())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, p := range []image.Point{
|
||||
{0, 0},
|
||||
} {
|
||||
c, err := cvs.Cell(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := cvs.SetCell(p, c.Rune, cell.FgColor(cell.ColorRed), cell.BgColor(cell.ColorBlue)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err := cvs.Apply(ft); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ft, nil
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "SetAreaCellOpts sets options in a sub-area",
|
||||
canvas: image.Rect(0, 0, 3, 3),
|
||||
ops: func(cvs *Canvas) error {
|
||||
return cvs.SetAreaCellOpts(image.Rect(0, 0, 2, 2), cell.FgColor(cell.ColorRed), cell.BgColor(cell.ColorBlue))
|
||||
},
|
||||
want: func(size image.Point) (*faketerm.Terminal, error) {
|
||||
ft := faketerm.MustNew(size)
|
||||
cvs, err := New(ft.Area())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, p := range []image.Point{
|
||||
{0, 0},
|
||||
{0, 1},
|
||||
{1, 0},
|
||||
{1, 1},
|
||||
} {
|
||||
c, err := cvs.Cell(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := cvs.SetCell(p, c.Rune, cell.FgColor(cell.ColorRed), cell.BgColor(cell.ColorBlue)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err := cvs.Apply(ft); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ft, nil
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
cvs, err := New(tc.canvas)
|
||||
if err != nil {
|
||||
t.Fatalf("New => unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if tc.ops != nil {
|
||||
err := tc.ops(cvs)
|
||||
if (err != nil) != tc.wantErr {
|
||||
t.Errorf("tc.ops => unexpected error: %v, wantErr: %v", err, tc.wantErr)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
size := cvs.Size()
|
||||
got, err := faketerm.New(size)
|
||||
if err != nil {
|
||||
t.Fatalf("faketerm.New => unexpected error: %v", err)
|
||||
}
|
||||
if err := cvs.Apply(got); err != nil {
|
||||
t.Fatalf("cvs.Apply => %v", err)
|
||||
}
|
||||
|
||||
var want *faketerm.Terminal
|
||||
if tc.want != nil {
|
||||
want, err = tc.want(size)
|
||||
if err != nil {
|
||||
t.Fatalf("tc.want => unexpected error: %v", err)
|
||||
}
|
||||
} else {
|
||||
w, err := faketerm.New(size)
|
||||
if err != nil {
|
||||
t.Fatalf("faketerm.New => unexpected error: %v", err)
|
||||
}
|
||||
want = w
|
||||
}
|
||||
|
||||
if diff := faketerm.Diff(want, got); diff != "" {
|
||||
t.Errorf("cvs.SetCellOpts => %v", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetCellAndApply(t *testing.T) {
|
||||
tests := []struct {
|
||||
desc string
|
||||
|
Loading…
x
Reference in New Issue
Block a user