diff --git a/container/container.go b/container/container.go index a4113a7..d44decd 100644 --- a/container/container.go +++ b/container/container.go @@ -64,7 +64,7 @@ func (c *Container) String() string { // New returns a new root container that will use the provided terminal and // applies the provided options. -func New(t terminalapi.Terminal, opts ...Option) *Container { +func New(t terminalapi.Terminal, opts ...Option) (*Container, error) { size := t.Size() root := &Container{ term: t, @@ -75,8 +75,10 @@ func New(t terminalapi.Terminal, opts ...Option) *Container { // Initially the root is focused. root.focusTracker = newFocusTracker(root) - applyOptions(root, opts...) - return root + if err := applyOptions(root, opts...); err != nil { + return nil, err + } + return root, nil } // newChild creates a new child container of the given parent. diff --git a/container/container_test.go b/container/container_test.go index 5e4eac8..e091837 100644 --- a/container/container_test.go +++ b/container/container_test.go @@ -33,7 +33,7 @@ import ( // Example demonstrates how to use the Container API. func Example() { - New( + if _, err := New( /* terminal = */ nil, SplitVertical( Left( @@ -58,20 +58,23 @@ func Example() { PlaceWidget(fakewidget.New(widgetapi.Options{})), ), ), - ) + ); err != nil { + panic(err) + } } func TestNew(t *testing.T) { tests := []struct { - desc string - termSize image.Point - container func(ft *faketerm.Terminal) *Container - want func(size image.Point) *faketerm.Terminal + desc string + termSize image.Point + container func(ft *faketerm.Terminal) (*Container, error) + wantContainerErr bool + want func(size image.Point) *faketerm.Terminal }{ { desc: "empty container", termSize: image.Point{10, 10}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New(ft) }, want: func(size image.Point) *faketerm.Terminal { @@ -81,7 +84,7 @@ func TestNew(t *testing.T) { { desc: "container with a border", termSize: image.Point{10, 10}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -102,7 +105,7 @@ func TestNew(t *testing.T) { { desc: "horizontal split, children have borders", termSize: image.Point{10, 10}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, SplitHorizontal( @@ -127,7 +130,7 @@ func TestNew(t *testing.T) { { desc: "horizontal split, parent and children have borders", termSize: image.Point{10, 10}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -158,7 +161,7 @@ func TestNew(t *testing.T) { { desc: "vertical split, children have borders", termSize: image.Point{10, 10}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, SplitVertical( @@ -183,7 +186,7 @@ func TestNew(t *testing.T) { { desc: "vertical split, parent and children have borders", termSize: image.Point{10, 10}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -214,7 +217,7 @@ func TestNew(t *testing.T) { { desc: "multi level split", termSize: image.Point{10, 16}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, SplitVertical( @@ -255,7 +258,7 @@ func TestNew(t *testing.T) { { desc: "inherits border and focused color", termSize: image.Point{10, 10}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -296,7 +299,7 @@ func TestNew(t *testing.T) { { desc: "splitting a container removes the widget", termSize: image.Point{10, 10}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -328,7 +331,7 @@ func TestNew(t *testing.T) { { desc: "placing a widget removes container split", termSize: image.Point{10, 10}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, SplitVertical( @@ -360,7 +363,14 @@ func TestNew(t *testing.T) { t.Fatalf("faketerm.New => unexpected error: %v", err) } - if err := tc.container(got).Draw(); err != nil { + cont, err := tc.container(got) + if (err != nil) != tc.wantContainerErr { + t.Errorf("tc.container => unexpected error:%v, wantErr:%v", err, tc.wantContainerErr) + } + if err != nil { + return + } + if err := cont.Draw(); err != nil { t.Fatalf("Draw => unexpected error: %v", err) } @@ -376,7 +386,7 @@ func TestKeyboard(t *testing.T) { tests := []struct { desc string termSize image.Point - container func(ft *faketerm.Terminal) *Container + container func(ft *faketerm.Terminal) (*Container, error) events []terminalapi.Event want func(size image.Point) *faketerm.Terminal wantErr bool @@ -384,7 +394,7 @@ func TestKeyboard(t *testing.T) { { desc: "event not forwarded if container has no widget", termSize: image.Point{10, 10}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New(ft) }, events: []terminalapi.Event{ @@ -397,7 +407,7 @@ func TestKeyboard(t *testing.T) { { desc: "event forwarded to focused container only", termSize: image.Point{40, 20}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, SplitVertical( @@ -450,7 +460,7 @@ func TestKeyboard(t *testing.T) { { desc: "event not forwarded if the widget didn't request it", termSize: image.Point{40, 20}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, PlaceWidget(fakewidget.New(widgetapi.Options{WantKeyboard: false})), @@ -473,7 +483,7 @@ func TestKeyboard(t *testing.T) { { desc: "widget returns an error when processing the event", termSize: image.Point{40, 20}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, PlaceWidget(fakewidget.New(widgetapi.Options{WantKeyboard: true})), @@ -503,7 +513,10 @@ func TestKeyboard(t *testing.T) { t.Fatalf("faketerm.New => unexpected error: %v", err) } - c := tc.container(got) + c, err := tc.container(got) + if err != nil { + t.Fatalf("tc.container => unexpected error: %v", err) + } for _, ev := range tc.events { switch e := ev.(type) { case *terminalapi.Mouse: @@ -537,7 +550,7 @@ func TestMouse(t *testing.T) { tests := []struct { desc string termSize image.Point - container func(ft *faketerm.Terminal) *Container + container func(ft *faketerm.Terminal) (*Container, error) events []terminalapi.Event want func(size image.Point) *faketerm.Terminal wantErr bool @@ -545,7 +558,7 @@ func TestMouse(t *testing.T) { { desc: "mouse click outside of the terminal is ignored", termSize: image.Point{10, 10}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, PlaceWidget(fakewidget.New(widgetapi.Options{WantMouse: true})), @@ -569,7 +582,7 @@ func TestMouse(t *testing.T) { { desc: "event not forwarded if container has no widget", termSize: image.Point{10, 10}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New(ft) }, events: []terminalapi.Event{ @@ -583,7 +596,7 @@ func TestMouse(t *testing.T) { { desc: "event forwarded to container at that point", termSize: image.Point{50, 20}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, SplitVertical( @@ -636,7 +649,7 @@ func TestMouse(t *testing.T) { { desc: "event not forwarded if the widget didn't request it", termSize: image.Point{20, 20}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, PlaceWidget(fakewidget.New(widgetapi.Options{WantMouse: false})), @@ -659,7 +672,7 @@ func TestMouse(t *testing.T) { { desc: "event not forwarded if it falls on the container's border", termSize: image.Point{20, 20}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -693,7 +706,7 @@ func TestMouse(t *testing.T) { { desc: "event not forwarded if it falls outside of widget's canvas", termSize: image.Point{20, 20}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, PlaceWidget( @@ -723,7 +736,7 @@ func TestMouse(t *testing.T) { { desc: "mouse poisition adjusted relative to widget's canvas, vertical offset", termSize: image.Point{20, 20}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, PlaceWidget( @@ -754,7 +767,7 @@ func TestMouse(t *testing.T) { { desc: "mouse poisition adjusted relative to widget's canvas, horizontal offset", termSize: image.Point{30, 20}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, PlaceWidget( @@ -785,7 +798,7 @@ func TestMouse(t *testing.T) { { desc: "widget returns an error when processing the event", termSize: image.Point{40, 20}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, PlaceWidget(fakewidget.New(widgetapi.Options{WantMouse: true})), @@ -815,7 +828,10 @@ func TestMouse(t *testing.T) { t.Fatalf("faketerm.New => unexpected error: %v", err) } - c := tc.container(got) + c, err := tc.container(got) + if err != nil { + t.Fatalf("tc.container => unexpected error: %v", err) + } for _, ev := range tc.events { switch e := ev.(type) { case *terminalapi.Mouse: diff --git a/container/draw_test.go b/container/draw_test.go index aa8bd91..6c4a273 100644 --- a/container/draw_test.go +++ b/container/draw_test.go @@ -32,14 +32,14 @@ func TestDrawWidget(t *testing.T) { tests := []struct { desc string termSize image.Point - container func(ft *faketerm.Terminal) *Container + container func(ft *faketerm.Terminal) (*Container, error) want func(size image.Point) *faketerm.Terminal wantErr bool }{ { desc: "draws widget with container border", termSize: image.Point{9, 5}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -66,7 +66,7 @@ func TestDrawWidget(t *testing.T) { { desc: "draws widget with container border and title aligned on the left", termSize: image.Point{9, 5}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -100,7 +100,7 @@ func TestDrawWidget(t *testing.T) { { desc: "draws widget with container border and title aligned in the center", termSize: image.Point{9, 5}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -135,7 +135,7 @@ func TestDrawWidget(t *testing.T) { { desc: "draws widget with container border and title aligned on the right", termSize: image.Point{9, 5}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -170,7 +170,7 @@ func TestDrawWidget(t *testing.T) { { desc: "draws widget with container border and title that is trimmed", termSize: image.Point{9, 5}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -205,7 +205,7 @@ func TestDrawWidget(t *testing.T) { { desc: "draws widget without container border", termSize: image.Point{9, 5}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, PlaceWidget(fakewidget.New(widgetapi.Options{})), @@ -225,7 +225,7 @@ func TestDrawWidget(t *testing.T) { { desc: "widget.Draw returns an error", termSize: image.Point{5, 5}, // Too small for the widget's box. - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -240,7 +240,7 @@ func TestDrawWidget(t *testing.T) { { desc: "container with border and no space isn't drawn", termSize: image.Point{1, 1}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -257,7 +257,7 @@ func TestDrawWidget(t *testing.T) { { desc: "container without the requested space for its widget isn't drawn", termSize: image.Point{1, 1}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, PlaceWidget(fakewidget.New(widgetapi.Options{ @@ -276,7 +276,7 @@ func TestDrawWidget(t *testing.T) { { desc: "widget's canvas is limited to the requested maximum size", termSize: image.Point{22, 22}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -308,7 +308,7 @@ func TestDrawWidget(t *testing.T) { { desc: "widget's canvas is limited to the requested maximum width", termSize: image.Point{22, 22}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -340,7 +340,7 @@ func TestDrawWidget(t *testing.T) { { desc: "widget's canvas is limited to the requested maximum height", termSize: image.Point{22, 22}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -372,7 +372,7 @@ func TestDrawWidget(t *testing.T) { { desc: "widget gets the requested aspect ratio", termSize: image.Point{22, 22}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -404,7 +404,7 @@ func TestDrawWidget(t *testing.T) { { desc: "widget's canvas is limited to the requested maximum size and ratio", termSize: image.Point{22, 22}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -436,7 +436,7 @@ func TestDrawWidget(t *testing.T) { { desc: "horizontal left align for the widget", termSize: image.Point{22, 22}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -467,7 +467,7 @@ func TestDrawWidget(t *testing.T) { { desc: "horizontal center align for the widget", termSize: image.Point{22, 22}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -498,7 +498,7 @@ func TestDrawWidget(t *testing.T) { { desc: "horizontal right align for the widget", termSize: image.Point{22, 22}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -529,7 +529,7 @@ func TestDrawWidget(t *testing.T) { { desc: "vertical top align for the widget", termSize: image.Point{22, 22}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -560,7 +560,7 @@ func TestDrawWidget(t *testing.T) { { desc: "vertical middle align for the widget", termSize: image.Point{22, 22}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -591,7 +591,7 @@ func TestDrawWidget(t *testing.T) { { desc: "vertical bottom align for the widget", termSize: image.Point{22, 22}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -624,8 +624,11 @@ func TestDrawWidget(t *testing.T) { for _, tc := range tests { t.Run(tc.desc, func(t *testing.T) { got := faketerm.MustNew(tc.termSize) - c := tc.container(got) - err := c.Draw() + c, err := tc.container(got) + if err != nil { + t.Fatalf("tc.container => unexpected error: %v", err) + } + err = c.Draw() if (err != nil) != tc.wantErr { t.Errorf("Draw => unexpected error: %v, wantErr: %v", err, tc.wantErr) } @@ -647,7 +650,7 @@ func TestDrawHandlesTerminalResize(t *testing.T) { t.Errorf("faketerm.New => unexpected error: %v", err) } - cont := New( + cont, err := New( got, SplitVertical( Left( @@ -672,6 +675,9 @@ func TestDrawHandlesTerminalResize(t *testing.T) { ), ), ) + if err != nil { + t.Fatalf("New => unexpected error: %v", err) + } // The following tests aren't hermetic, they all access the same container // and fake terminal in order to retain state between resizes. diff --git a/container/focus_test.go b/container/focus_test.go index 0ea2a89..c9331e8 100644 --- a/container/focus_test.go +++ b/container/focus_test.go @@ -37,13 +37,13 @@ func TestPointCont(t *testing.T) { tests := []struct { desc string termSize image.Point - container func(ft *faketerm.Terminal) *Container + container func(ft *faketerm.Terminal) (*Container, error) cases []pointCase }{ { desc: "single container, no border", termSize: image.Point{3, 3}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, BorderColor(cell.ColorBlue), @@ -90,7 +90,7 @@ func TestPointCont(t *testing.T) { { desc: "single container, border", termSize: image.Point{3, 3}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -113,7 +113,7 @@ func TestPointCont(t *testing.T) { { desc: "split containers, parent has no border", termSize: image.Point{10, 10}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, BorderColor(cell.ColorBlack), @@ -160,7 +160,7 @@ func TestPointCont(t *testing.T) { { desc: "split containers, parent has border", termSize: image.Point{10, 10}, - container: func(ft *faketerm.Terminal) *Container { + container: func(ft *faketerm.Terminal) (*Container, error) { return New( ft, Border(draw.LineStyleLight), @@ -229,7 +229,10 @@ func TestPointCont(t *testing.T) { t.Fatalf("faketerm.New => unexpected error: %v", err) } - cont := tc.container(ft) + cont, err := tc.container(ft) + if err != nil { + t.Fatalf("tc.container => unexpected error: %v", err) + } for _, pc := range tc.cases { gotCont := pointCont(cont, pc.point) if (gotCont == nil) != pc.wantNil { @@ -382,13 +385,16 @@ func TestFocusTrackerMouse(t *testing.T) { for _, tc := range tests { t.Run(tc.desc, func(t *testing.T) { - root := New( + root, err := New( ft, SplitVertical( Left(), Right(), ), ) + if err != nil { + t.Fatalf("New => unexpected error: %v", err) + } for _, ev := range tc.events { root.Mouse(ev) diff --git a/container/options.go b/container/options.go index 773f319..df5d1ee 100644 --- a/container/options.go +++ b/container/options.go @@ -24,16 +24,19 @@ import ( ) // applyOptions applies the options to the container. -func applyOptions(c *Container, opts ...Option) { +func applyOptions(c *Container, opts ...Option) error { for _, opt := range opts { - opt.set(c) + if err := opt.set(c); err != nil { + return err + } } + return nil } // Option is used to provide options to a container. type Option interface { // set sets the provided option. - set(*Container) + set(*Container) error } // options stores the options provided to the container. @@ -85,22 +88,24 @@ func newOptions(parent *options) *options { } // option implements Option. -type option func(*Container) +type option func(*Container) error // set implements Option.set. -func (o option) set(c *Container) { - o(c) +func (o option) set(c *Container) error { + return o(c) } // SplitVertical splits the container along the vertical axis into two sub // containers. The use of this option removes any widget placed at this // container, containers with sub containers cannot contain widgets. func SplitVertical(l LeftOption, r RightOption) Option { - return option(func(c *Container) { + return option(func(c *Container) error { c.opts.split = splitTypeVertical c.opts.widget = nil - applyOptions(c.createFirst(), l.lOpts()...) - applyOptions(c.createSecond(), r.rOpts()...) + if err := applyOptions(c.createFirst(), l.lOpts()...); err != nil { + return err + } + return applyOptions(c.createSecond(), r.rOpts()...) }) } @@ -108,11 +113,13 @@ func SplitVertical(l LeftOption, r RightOption) Option { // containers. The use of this option removes any widget placed at this // container, containers with sub containers cannot contain widgets. func SplitHorizontal(t TopOption, b BottomOption) Option { - return option(func(c *Container) { + return option(func(c *Container) error { c.opts.split = splitTypeHorizontal c.opts.widget = nil - applyOptions(c.createFirst(), t.tOpts()...) - applyOptions(c.createSecond(), b.bOpts()...) + if err := applyOptions(c.createFirst(), t.tOpts()...); err != nil { + return err + } + return applyOptions(c.createSecond(), b.bOpts()...) }) } @@ -120,10 +127,11 @@ func SplitHorizontal(t TopOption, b BottomOption) Option { // The use of this option removes any sub containers. Containers with sub // containers cannot have widgets. func PlaceWidget(w widgetapi.Widget) Option { - return option(func(c *Container) { + return option(func(c *Container) error { c.opts.widget = w c.first = nil c.second = nil + return nil }) } @@ -131,8 +139,9 @@ func PlaceWidget(w widgetapi.Widget) Option { // container. Has no effect if the container contains no widget. // Defaults alignment in the center. func AlignHorizontal(h align.Horizontal) Option { - return option(func(c *Container) { + return option(func(c *Container) error { c.opts.hAlign = h + return nil }) } @@ -140,51 +149,58 @@ func AlignHorizontal(h align.Horizontal) Option { // Has no effect if the container contains no widget. // Defaults to alignment in the middle. func AlignVertical(v align.Vertical) Option { - return option(func(c *Container) { + return option(func(c *Container) error { c.opts.vAlign = v + return nil }) } // Border configures the container to have a border of the specified style. func Border(ls draw.LineStyle) Option { - return option(func(c *Container) { + return option(func(c *Container) error { c.opts.border = ls + return nil }) } // BorderTitle sets a text title within the border. func BorderTitle(title string) Option { - return option(func(c *Container) { + return option(func(c *Container) error { c.opts.borderTitle = title + return nil }) } // BorderTitleAlignLeft aligns the border title on the left. func BorderTitleAlignLeft() Option { - return option(func(c *Container) { + return option(func(c *Container) error { c.opts.borderTitleHAlign = align.HorizontalLeft + return nil }) } // BorderTitleAlignCenter aligns the border title in the center. func BorderTitleAlignCenter() Option { - return option(func(c *Container) { + return option(func(c *Container) error { c.opts.borderTitleHAlign = align.HorizontalCenter + return nil }) } // BorderTitleAlignRight aligns the border title on the right. func BorderTitleAlignRight() Option { - return option(func(c *Container) { + return option(func(c *Container) error { c.opts.borderTitleHAlign = align.HorizontalRight + return nil }) } // BorderColor sets the color of the border around the container. // This option is inherited to sub containers created by container splits. func BorderColor(color cell.Color) Option { - return option(func(c *Container) { + return option(func(c *Container) error { c.opts.inherited.borderColor = color + return nil }) } @@ -192,8 +208,9 @@ func BorderColor(color cell.Color) Option { // keyboard focus. // This option is inherited to sub containers created by container splits. func FocusedColor(color cell.Color) Option { - return option(func(c *Container) { + return option(func(c *Container) error { c.opts.inherited.focusedColor = color + return nil }) } diff --git a/container/traversal_test.go b/container/traversal_test.go index 338576b..f31ae66 100644 --- a/container/traversal_test.go +++ b/container/traversal_test.go @@ -30,7 +30,7 @@ func TestRoot(t *testing.T) { if err != nil { t.Fatalf("faketerm.New => unexpected error: %v", err) } - want := New( + want, err := New( ft, SplitHorizontal( Top( @@ -42,6 +42,9 @@ func TestRoot(t *testing.T) { Bottom(), ), ) + if err != nil { + t.Fatalf("New => unexpected error: %v", err) + } if got := rootCont(want); got != want { t.Errorf("rootCont(root) => got %p, want %p", got, want) @@ -58,7 +61,7 @@ func TestTraversal(t *testing.T) { if err != nil { t.Fatalf("faketerm.New => unexpected error: %v", err) } - cont := New( + cont, err := New( ft, BorderColor(cell.ColorBlack), SplitVertical( @@ -86,6 +89,9 @@ func TestTraversal(t *testing.T) { ), ), ) + if err != nil { + t.Fatalf("New => unexpected error: %v", err) + } tests := []struct { desc string diff --git a/termdash_test.go b/termdash_test.go index d5de9fc..c561bb6 100644 --- a/termdash_test.go +++ b/termdash_test.go @@ -50,7 +50,7 @@ func Example() { } // Create the container with two fake widgets. - c := container.New( + c, err := container.New( t, container.SplitVertical( container.Left( @@ -61,6 +61,9 @@ func Example() { ), ), ) + if err != nil { + panic(err) + } // Termdash runs until the context expires. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) @@ -86,10 +89,13 @@ func Example_triggered() { } // Create the container with a widget. - c := container.New( + c, err := container.New( t, container.PlaceWidget(fakewidget.New(wOpts)), ) + if err != nil { + panic(err) + } // Create the controller and disable periodic redraw. ctrl, err := NewController(t, c) @@ -332,13 +338,16 @@ func TestRun(t *testing.T) { t.Fatalf("faketerm.New => unexpected error: %v", err) } - cont := container.New( + cont, err := container.New( got, container.PlaceWidget(fakewidget.New(widgetapi.Options{ WantKeyboard: true, WantMouse: true, })), ) + if err != nil { + t.Fatalf("container.New => unexpected error: %v", err) + } ctx, cancel := context.WithTimeout(context.Background(), 5*time.Millisecond) err = Run(ctx, got, cont, tc.opts...) @@ -511,10 +520,13 @@ func TestController(t *testing.T) { WantKeyboard: true, WantMouse: true, }) - cont := container.New( + cont, err := container.New( got, container.PlaceWidget(mi), ) + if err != nil { + t.Fatalf("container.New => unexpected error: %v", err) + } ctrl, err := NewController(got, cont, tc.opts...) if (err != nil) != tc.wantErr { diff --git a/widgets/barchart/barchartdemo/barchartdemo.go b/widgets/barchart/barchartdemo/barchartdemo.go index 6406dfe..9c06113 100644 --- a/widgets/barchart/barchartdemo/barchartdemo.go +++ b/widgets/barchart/barchartdemo/barchartdemo.go @@ -93,12 +93,15 @@ func main() { ) go playBarChart(ctx, bc, 1*time.Second) - c := container.New( + c, err := container.New( t, container.Border(draw.LineStyleLight), container.BorderTitle("PRESS Q TO QUIT"), container.PlaceWidget(bc), ) + if err != nil { + panic(err) + } quitter := func(k *terminalapi.Keyboard) { if k.Key == 'q' || k.Key == 'Q' { diff --git a/widgets/gauge/demo/gaugedemo.go b/widgets/gauge/demo/gaugedemo.go index f65fc2e..2a55910 100644 --- a/widgets/gauge/demo/gaugedemo.go +++ b/widgets/gauge/demo/gaugedemo.go @@ -115,7 +115,7 @@ func main() { ) go playGauge(ctx, withLabel, 3, 500*time.Millisecond, playTypePercent) - c := container.New( + c, err := container.New( t, container.SplitVertical( container.Left( @@ -147,6 +147,9 @@ func main() { ), ), ) + if err != nil { + panic(err) + } quitter := func(k *terminalapi.Keyboard) { if k.Key == 'q' || k.Key == 'Q' { diff --git a/widgets/linechart/linechartdemo/linechartdemo.go b/widgets/linechart/linechartdemo/linechartdemo.go index e1bbc4c..9f06a53 100644 --- a/widgets/linechart/linechartdemo/linechartdemo.go +++ b/widgets/linechart/linechartdemo/linechartdemo.go @@ -88,12 +88,15 @@ func main() { linechart.XLabelCellOpts(cell.FgColor(cell.ColorCyan)), ) go playLineChart(ctx, lc, redrawInterval/3) - c := container.New( + c, err := container.New( t, container.Border(draw.LineStyleLight), container.BorderTitle("PRESS Q TO QUIT"), container.PlaceWidget(lc), ) + if err != nil { + panic(err) + } quitter := func(k *terminalapi.Keyboard) { if k.Key == 'q' || k.Key == 'Q' { diff --git a/widgets/sparkline/sparklinedemo/sparklinedemo.go b/widgets/sparkline/sparklinedemo/sparklinedemo.go index be5d1e2..6d9232f 100644 --- a/widgets/sparkline/sparklinedemo/sparklinedemo.go +++ b/widgets/sparkline/sparklinedemo/sparklinedemo.go @@ -75,7 +75,7 @@ func main() { ) go playSparkLine(ctx, yellow, 1*time.Second) - c := container.New( + c, err := container.New( t, container.Border(draw.LineStyleLight), container.BorderTitle("PRESS Q TO QUIT"), @@ -103,6 +103,9 @@ func main() { ), ), ) + if err != nil { + panic(err) + } quitter := func(k *terminalapi.Keyboard) { if k.Key == 'q' || k.Key == 'Q' { diff --git a/widgets/text/demo/textdemo.go b/widgets/text/demo/textdemo.go index 3ddd331..863f8ab 100644 --- a/widgets/text/demo/textdemo.go +++ b/widgets/text/demo/textdemo.go @@ -106,7 +106,7 @@ func main() { } go writeLines(ctx, rolled, 1*time.Second) - c := container.New( + c, err := container.New( t, container.Border(draw.LineStyleLight), container.BorderTitle("PRESS Q TO QUIT"), @@ -148,6 +148,9 @@ func main() { ), ), ) + if err != nil { + panic(err) + } quitter := func(k *terminalapi.Keyboard) { if k.Key == 'q' || k.Key == 'Q' {