diff --git a/README.md b/README.md index 8331932..3cf681d 100644 --- a/README.md +++ b/README.md @@ -130,7 +130,7 @@ func main() { - `Colors` must have the same number of entries as `Title` — `NewCmdBanner` returns an error otherwise. - `Title` segments are concatenated with no separator, so include spacing in the segments themselves if you want it. -- `TopPadding` defaults to `true`, which adds a single leading newline before the rendered output (use `WithZeroPadding()` to disable this). +- `TopPadding` defaults to `1`, which adds a single leading newline before the rendered output (use `WithPadding(0, 0)` to disable this). - `CmdBanner` and `PrintCmdBanner` both return an error if `FontPath` fails to load or rendering fails (e.g. `FontName` can't be found). #### Banner functional options @@ -140,7 +140,8 @@ func main() { | `WithColors(colors ...string)` | Sets the color palette, one per `Title` segment. Each string is resolved with `ResolveColor`. | | `WithFont(name string)` | Selects a builtin or already-loaded font by name. | | `WithLocalFont(name, path string)` | Sets the font name *and* a directory to load additional fonts from. | -| `WithZeroPadding()` | Disables the default leading newline (`TopPadding = false`). | +| `WithPadding(top, bottom int)` | Sets the number of newlines before (`top`) and after (`bottom`) the rendered output. | +| `WithZeroPadding()` | Convenience wrapper for `WithPadding(0, 0)` to disable both top and bottom padding. | #### Screenshot diff --git a/banner.go b/banner.go index ebc20ac..e975eda 100644 --- a/banner.go +++ b/banner.go @@ -26,9 +26,12 @@ type Banner struct { // FontPath, if set, is an on-disk directory to load additional fonts // from (in addition to the embedded builtin fonts) before rendering. FontPath string - // TopPadding, if true, adds a single leading newline before the + // TopPadding is the number of leading newlines to add before the // rendered output. It does not affect kerning or layout. - TopPadding bool + TopPadding int + // BottomPadding is the number of trailing newlines to add after the + // rendered output. + BottomPadding int } // BannerOptions configures a Banner via the functional options pattern. @@ -56,13 +59,21 @@ func WithLocalFont(f string, p string) BannerOptions { } } -// WithZeroPadding disables the leading newline added by default when TopPadding is true. -func WithZeroPadding() BannerOptions { +// WithPadding sets the number of newlines to add before (top) and after +// (bottom) the rendered output. Pass 0 to disable padding on either side. +func WithPadding(top, bottom int) BannerOptions { return func(b *Banner) { - b.TopPadding = false + b.TopPadding = top + b.BottomPadding = bottom } } +// WithZeroPadding is a convenience wrapper around WithPadding(0, 0) that +// disables both top and bottom padding. +func WithZeroPadding() BannerOptions { + return WithPadding(0, 0) +} + // NewCmdBanner creates a Banner with sensible defaults for CLI tool banners. // Title entries represent command and subcommand names (e.g., ["cmd", "sub"]). // Colors must match the number of Title entries. @@ -71,7 +82,7 @@ func NewCmdBanner(title []string, options ...BannerOptions) (*Banner, error) { Title: title, Colors: []color.Color{ColorCyan, TrueColorPink206}, FontName: "smallsmursh", - TopPadding: true, + TopPadding: 1, } for _, o := range options { o(b) @@ -119,7 +130,7 @@ func CmdBanner(b *Banner) (string, error) { figletOptions.FontColor = figletColors var renderedString strings.Builder - if b.TopPadding { + for i := 0; i < b.TopPadding; i++ { renderedString.WriteByte('\n') } @@ -129,6 +140,10 @@ func CmdBanner(b *Banner) (string, error) { } renderedString.WriteString(asciiString) + for i := 0; i < b.BottomPadding; i++ { + renderedString.WriteByte('\n') + } + return renderedString.String(), nil } diff --git a/banner_test.go b/banner_test.go new file mode 100644 index 0000000..39e2f27 --- /dev/null +++ b/banner_test.go @@ -0,0 +1,78 @@ +package gofiglet + +import ( + "image/color" + "strings" + "testing" +) + +func TestNewCmdBanner_DefaultPadding(t *testing.T) { + b, err := NewCmdBanner([]string{"Test"}, WithColors([]color.Color{ColorCyan})) + if err != nil { + t.Fatalf("NewCmdBanner() error = %v", err) + } + if b.TopPadding != 1 { + t.Errorf("default TopPadding = %d, want 1", b.TopPadding) + } + if b.BottomPadding != 0 { + t.Errorf("default BottomPadding = %d, want 0", b.BottomPadding) + } +} + +func TestWithPadding(t *testing.T) { + b, err := NewCmdBanner([]string{"Test"}, WithPadding(3, 2), WithColors([]color.Color{ColorCyan})) + if err != nil { + t.Fatalf("NewCmdBanner() error = %v", err) + } + if b.TopPadding != 3 { + t.Errorf("TopPadding = %d, want 3", b.TopPadding) + } + if b.BottomPadding != 2 { + t.Errorf("BottomPadding = %d, want 2", b.BottomPadding) + } +} + +func TestCmdBanner_TopPadding(t *testing.T) { + b, err := NewCmdBanner([]string{"Test"}, WithPadding(2, 0), WithColors([]color.Color{ColorCyan})) + if err != nil { + t.Fatalf("NewCmdBanner() error = %v", err) + } + result, err := CmdBanner(b) + if err != nil { + t.Fatalf("CmdBanner() error = %v", err) + } + if !strings.HasPrefix(result, "\n\n") { + t.Errorf("expected 2 leading newlines from TopPadding=2, got: %q", result[:min(20, len(result))]) + } + if strings.HasPrefix(result, "\n\n\n") { + t.Errorf("expected exactly 2 leading newlines from TopPadding=2, got 3") + } +} + +func TestCmdBanner_BottomPadding(t *testing.T) { + b, err := NewCmdBanner([]string{"Test"}, WithPadding(0, 2), WithColors([]color.Color{ColorCyan})) + if err != nil { + t.Fatalf("NewCmdBanner() error = %v", err) + } + result, err := CmdBanner(b) + if err != nil { + t.Fatalf("CmdBanner() error = %v", err) + } + if !strings.HasSuffix(result, "\n\n\n") { + t.Errorf("expected 3 trailing newlines (renderer \\n + BottomPadding=2), got: %q", result[max(0, len(result)-20):]) + } +} + +func TestCmdBanner_NoPadding(t *testing.T) { + b, err := NewCmdBanner([]string{"Test"}, WithPadding(0, 0), WithColors([]color.Color{ColorCyan})) + if err != nil { + t.Fatalf("NewCmdBanner() error = %v", err) + } + result, err := CmdBanner(b) + if err != nil { + t.Fatalf("CmdBanner() error = %v", err) + } + if strings.HasPrefix(result, "\n") { + t.Errorf("expected no leading newline with TopPadding=0, got: %q", result[:min(20, len(result))]) + } +}