Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 23 additions & 33 deletions internal/welcome/welcome.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down Expand Up @@ -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()
}

Expand All @@ -112,28 +112,18 @@ 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
}
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')
}
4 changes: 2 additions & 2 deletions internal/welcome/welcome.xdocs.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -21,4 +21,4 @@ status: draft

#### &copy; 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.
48 changes: 42 additions & 6 deletions internal/welcome/welcome_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,37 +10,73 @@ 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"} {
if strings.Contains(output, forbidden) {
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} {
if !strings.Contains(output, color) {
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)
}
Expand Down