From e3ba6b34bbaba55dac235f8ef452674912164d89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20GUIHO?= Date: Tue, 13 Oct 2026 14:10:09 +0200 Subject: [PATCH] Left-align the welcome message Render the bare `buda` welcome flush left: the logo rows, tagline and GUIHO attribution line no longer receive centering padding, and the detail lines start at column 0 with their values aligned. - Capitalise the detail labels (Platform, Version) and add an Author line "GUIHO (www.guiho.co)" with the website in the accent colour. - Use one blank line between the attribution and the details, and exactly one leading and one trailing blank line. - Remove the now-unused center helper and width computation. - Pin the exact plain-text layout and the accent colouring in tests. Co-Authored-By: Claude Opus 5.5 --- internal/welcome/welcome.go | 56 +++++++++++++------------------ internal/welcome/welcome.xdocs.md | 4 +-- internal/welcome/welcome_test.go | 48 ++++++++++++++++++++++---- 3 files changed, 67 insertions(+), 41 deletions(-) diff --git a/internal/welcome/welcome.go b/internal/welcome/welcome.go index 8f48fe5..e84bb2f 100644 --- a/internal/welcome/welcome.go +++ b/internal/welcome/welcome.go @@ -18,6 +18,10 @@ const ( ansiOcean = "\x1b[38;2;58;124;165m" // 3A7CA5 ansiMist = "\x1b[38;2;217;220;214m" // D9DCD6 light ansiSky = "\x1b[38;2;129;195;215m" // 81C3D7 + + // ansiAccent is Buda's primary brand colour, used for the GUIHO + // attribution and the website in the Author detail. + ansiAccent = ansiOcean ) var platformLabels = map[string]string{ @@ -76,32 +80,28 @@ func render(platform, architecture, version string, withColor bool) string { architecture = displayValue(archLabels, architecture) version = strings.TrimPrefix(strings.TrimSpace(version), "v") - innerWidth := 56 - for _, line := range budaLogo { - if width := len([]rune(line)); width > innerWidth { - innerWidth = width - } - } - innerWidth += 4 - var output strings.Builder - output.WriteString("\n\n") + output.WriteString("\n") for index, line := range budaLogo { - output.WriteString(colorize(withColor, center(line, innerWidth), logoColors[index]+ansiBold)) + output.WriteString(colorize(withColor, line, logoColors[index]+ansiBold)) output.WriteByte('\n') } - output.WriteString(colorize(withColor, center("AI-maintained OKF wiki", innerWidth), ansiSky+ansiDim)) + output.WriteString(colorize(withColor, "AI-maintained OKF wiki", ansiSky+ansiDim)) output.WriteByte('\n') - output.WriteString(colorize(withColor, center("GUIHO \u00b7 Crist\u00f3v\u00e3o GUIHO", innerWidth), ansiOcean)) - output.WriteString("\n\n\n") + output.WriteString(colorize(withColor, "GUIHO \u00b7 Crist\u00f3v\u00e3o GUIHO", ansiAccent)) + output.WriteString("\n\n") - writeDetail(&output, withColor, "platform", platform+" "+architecture, ansiMist) - writeDetail(&output, withColor, "version", "v"+version, ansiSky+ansiBold) + writeDetail(&output, withColor, "Platform", colorize(withColor, platform+" "+architecture, ansiMist)) + writeDetail(&output, withColor, "Version", colorize(withColor, "v"+version, ansiSky+ansiBold)) + writeDetail(&output, withColor, "Author", + colorize(withColor, "GUIHO (", ansiMist)+ + colorize(withColor, "www.guiho.co", ansiAccent)+ + colorize(withColor, ")", ansiMist)) output.WriteByte('\n') output.WriteString("Run ") output.WriteString(colorize(withColor, "buda --help", ansiMist+ansiBold)) output.WriteString(" to see available commands.\n") - output.WriteString("\n\n") + output.WriteString("\n") return output.String() } @@ -112,14 +112,6 @@ func displayValue(labels map[string]string, value string) string { return value } -func center(value string, width int) string { - padding := width - len([]rune(value)) - if padding <= 0 { - return value - } - return strings.Repeat(" ", padding/2) + value -} - func colorize(enabled bool, value, codes string) string { if !enabled { return value @@ -127,13 +119,11 @@ func colorize(enabled bool, value, codes string) string { return codes + value + ansiReset } -func writeDetail(output *strings.Builder, withColor bool, label, value, valueColor string) { - if withColor { - output.WriteString(colorize(true, fmt.Sprintf(" %-9s", label), ansiOceanDark)) - output.WriteString(" ") - output.WriteString(colorize(true, value, valueColor)) - output.WriteByte('\n') - return - } - fmt.Fprintf(output, " %-9s %s\n", label, value) +// writeDetail writes one left-aligned detail line. value is already +// colorized by the caller when colour is enabled. +func writeDetail(output *strings.Builder, withColor bool, label, value string) { + output.WriteString(colorize(withColor, fmt.Sprintf("%-8s", label), ansiOceanDark)) + output.WriteString(" ") + output.WriteString(value) + output.WriteByte('\n') } diff --git a/internal/welcome/welcome.xdocs.md b/internal/welcome/welcome.xdocs.md index 4c04f75..79eadbd 100644 --- a/internal/welcome/welcome.xdocs.md +++ b/internal/welcome/welcome.xdocs.md @@ -5,7 +5,7 @@ parent: buda-internal children: [] files: welcome.go: Deterministic borderless hello window using the approved Buda palette 2F6690, 3A7CA5, D9DCD6, 16425B, 81C3D7 with platform/version normalization and NO_COLOR/TERM handling. - welcome_test.go: Exact hello-window output, complete palette, and no-color contract tests. + welcome_test.go: Exact left-aligned hello-window output, complete palette, and no-color contract tests. documents: {} tags: - welcome @@ -21,4 +21,4 @@ status: draft #### © 2026 [GUIHO](https://guiho.co) as represented by [Cristóvão GUIHO](https://guiho.co/cguiho) All Rights Reserved. -This package owns the deterministic borderless hello window shown only by a bare `buda` invocation. It prints the Buda block logo, the AI-maintained OKF wiki tagline, and the GUIHO attribution, then lists platform, version, and the help hint. Color uses the approved palette when the terminal is compatible; NO_COLOR and TERM=dumb always disable color. Help, version, and explicit subcommands never print the hello window. +This package owns the deterministic borderless hello window shown only by a bare `buda` invocation. It prints the left-aligned Buda block logo, the AI-maintained OKF wiki tagline, and the GUIHO attribution, then lists left-aligned Platform, Version, and Author (GUIHO, with www.guiho.co in the accent colour) details with aligned values, and the help hint, framed by one leading and one trailing blank line. Color uses the approved palette when the terminal is compatible; NO_COLOR and TERM=dumb always disable color. Help, version, and explicit subcommands never print the hello window. diff --git a/internal/welcome/welcome_test.go b/internal/welcome/welcome_test.go index 9d51243..55f2021 100644 --- a/internal/welcome/welcome_test.go +++ b/internal/welcome/welcome_test.go @@ -10,18 +10,18 @@ func TestRenderBorderlessHelloWindow(t *testing.T) { for _, required := range []string{ "██████╗ ██╗ ██╗██████╗", "AI-maintained OKF wiki", "GUIHO \u00b7 Crist\u00f3v\u00e3o GUIHO", - "platform Windows x64", "version v1.2.3", + "Platform Windows x64", "Version v1.2.3", "Author GUIHO (www.guiho.co)", "Run buda --help to see available commands.", } { if !strings.Contains(output, required) { t.Fatalf("welcome output omits %q:\n%s", required, output) } } - if !strings.HasPrefix(output, "\n\n") { - t.Fatal("welcome output does not start with two blank lines") + if !strings.HasPrefix(output, "\n") || strings.HasPrefix(output, "\n\n") { + t.Fatal("welcome output does not start with exactly one blank line") } - if !strings.HasSuffix(output, "\n\n") { - t.Fatal("welcome output does not end with two blank lines") + if !strings.HasSuffix(output, "commands.\n\n") { + t.Fatal("welcome output does not end with exactly one blank line") } // Should be borderless and deterministic for _, forbidden := range []string{"\x1b[", "╭", "╰", "Hello Windows - buda"} { @@ -29,11 +29,40 @@ func TestRenderBorderlessHelloWindow(t *testing.T) { t.Fatalf("welcome output contains %q:\n%s", forbidden, output) } } - if strings.Count(output, "platform") != 1 || strings.Count(output, "version") != 1 { + if strings.Count(output, "Platform") != 1 || strings.Count(output, "Version") != 1 || strings.Count(output, "Author") != 1 { t.Fatalf("welcome output has duplicate detail lines: %q", output) } } +func TestRenderIsLeftAlignedWithoutCreatorLine(t *testing.T) { + output := Render("linux", "amd64", "1.2.3") + var expected strings.Builder + expected.WriteString("\n") + for _, line := range budaLogo { + expected.WriteString(line + "\n") + } + expected.WriteString("AI-maintained OKF wiki\n") + expected.WriteString("GUIHO \u00b7 Crist\u00f3v\u00e3o GUIHO\n") + expected.WriteString("\n") + expected.WriteString("Platform Linux x64\n") + expected.WriteString("Version v1.2.3\n") + expected.WriteString("Author GUIHO (www.guiho.co)\n") + expected.WriteString("\n") + expected.WriteString("Run buda --help to see available commands.\n") + expected.WriteString("\n") + if output != expected.String() { + t.Fatalf("welcome output mismatch:\n got: %q\nwant: %q", output, expected.String()) + } + if strings.Contains(output, "Creator") { + t.Fatalf("welcome output contains a Creator line:\n%s", output) + } + for _, line := range strings.Split(output, "\n") { + if strings.HasPrefix(line, " ") { + t.Fatalf("welcome line is not left-aligned: %q", line) + } + } +} + func TestRenderWithColorUsesCompleteBudaPalette(t *testing.T) { output := RenderWithColor("linux", "arm64", "v2.0.0", true) for _, color := range []string{ansiMist, ansiSky, ansiOcean, ansiOceanDark, ansiNavy} { @@ -41,6 +70,13 @@ func TestRenderWithColorUsesCompleteBudaPalette(t *testing.T) { t.Fatalf("colored welcome omits palette code %q", color) } } + if !strings.Contains(output, ansiOceanDark+"Platform"+ansiReset+" ") || !strings.Contains(output, ansiOceanDark+"Version "+ansiReset+" ") || !strings.Contains(output, ansiOceanDark+"Author "+ansiReset+" ") { + t.Fatalf("colored welcome detail labels are not left-aligned: %q", output) + } + authorValue := ansiMist + "GUIHO (" + ansiReset + ansiAccent + "www.guiho.co" + ansiReset + ansiMist + ")" + ansiReset + if !strings.Contains(output, authorValue) { + t.Fatalf("colored welcome does not paint the website in the accent colour: %q", output) + } if !strings.Contains(output, "Linux arm64") || !strings.Contains(output, "v2.0.0") { t.Fatalf("colored welcome omits normalized runtime details: %q", output) }