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
13 changes: 8 additions & 5 deletions cmd/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,18 +392,21 @@ func TestNoArgumentVersionAndCatalog(t *testing.T) {
for _, required := range []string{
"████╗", "Structured documentation for codebases and AI agents",
"GUIHO", "Cristóvão GUIHO",
"organization", "platform", "x64", "version", "v0.8.0",
"\n\nPlatform ", "x64", "\nVersion v0.8.0\nAuthor GUIHO (www.guiho.co)\n\n",
"Run xdocs --help to see available commands.",
} {
if !strings.Contains(out, required) {
t.Fatalf("welcome output omits %q:\n%s", required, out)
}
}
if !strings.HasPrefix(out, "\n\n") {
t.Fatalf("welcome output does not start with two blank lines: %q", out)
if strings.Contains(out, "organization") || strings.Contains(out, "Creator") {
t.Fatalf("welcome output still shows a creator/organization detail line:\n%s", out)
}
if !strings.HasSuffix(out, "\n\n") {
t.Fatalf("welcome output does not end with two blank lines: %q", out)
if !strings.HasPrefix(out, "\n██") || strings.HasPrefix(out, "\n\n") {
t.Fatalf("welcome output does not start with exactly one blank line: %q", out)
}
if !strings.HasSuffix(out, "commands.\n\n") || strings.HasSuffix(out, "\n\n\n") {
t.Fatalf("welcome output does not end with exactly one blank line: %q", out)
}
if strings.Contains(out, "Hello Windows") || strings.Contains(out, "\x1b[") {
t.Fatalf("welcome output should be beautiful borderless without legacy text or ANSI in non-terminal mode: %q", out)
Expand Down
69 changes: 26 additions & 43 deletions internal/welcome/welcome.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ const (
ansiCream = "\x1b[38;2;237;224;212m"
ansiSage = "\x1b[38;2;101;109;74m"
ansiForest = "\x1b[38;2;65;72;51m"

// ansiAccent is the xdocs primary accent: the warm brown logo tone.
ansiAccent = ansiBrown + ansiBold
)

var platformLabels = map[string]string{
Expand Down Expand Up @@ -83,45 +86,39 @@ 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 xdocsLogo {
if w := len([]rune(line)); w+4 > innerWidth {
innerWidth = w + 4
}
}
tagline := "Structured documentation for codebases and AI agents"
if len([]rune(tagline))+4 > innerWidth {
innerWidth = len([]rune(tagline)) + 4
}

var out strings.Builder
// Two blank lines before — as requested
out.WriteString("\n\n")
// One blank line before, so the welcome never touches the prompt line
out.WriteString("\n")

for i, line := range xdocsLogo {
color := ""
if i < len(logoColors) {
color = logoColors[i]
}
out.WriteString(colorize(withColor, center(line, innerWidth), color))
out.WriteString(colorize(withColor, line, color))
out.WriteByte('\n')
}
out.WriteString(colorize(withColor, center(tagline, innerWidth), ansiTan+ansiDim))
out.WriteString(colorize(withColor, tagline, ansiTan+ansiDim))
out.WriteByte('\n')
out.WriteString(colorize(withColor, center("GUIHO · Cristóvão GUIHO", innerWidth), ansiSage))
out.WriteString("\n\n\n")
out.WriteString(colorize(withColor, "GUIHO · Cristóvão GUIHO", ansiSage))
out.WriteString("\n\n")

// Details — organization, platform, version
writeDetail(&out, withColor, "organization", "GUIHO", ansiCream+ansiBold)
writeDetail(&out, withColor, "platform", platform+" "+architecture, ansiCream)
writeDetail(&out, withColor, "version", "v"+version, ansiBrown+ansiBold)
// Details — platform, version, author
writeDetail(&out, withColor, "Platform", colorize(withColor, platform+" "+architecture, ansiCream))
writeDetail(&out, withColor, "Version", colorize(withColor, "v"+version, ansiAccent))
writeDetail(&out, withColor, "Author",
colorize(withColor, "GUIHO (", ansiCream)+
colorize(withColor, "www.guiho.co", ansiAccent)+
colorize(withColor, ")", ansiCream))
out.WriteByte('\n')
out.WriteString("Run ")
out.WriteString(colorize(withColor, "xdocs --help", ansiCream+ansiBold))
out.WriteString(" to see available commands.")
out.WriteString("\n")
// Two blank lines after — as requested
out.WriteString("\n\n")
// One blank line after, so the welcome never touches the next prompt
out.WriteString("\n")
return out.String()
}

Expand All @@ -132,33 +129,19 @@ func displayValue(labels map[string]string, value string) string {
return value
}

func center(value string, width int) string {
w := len([]rune(value))
if w >= width {
return value
}
pad := width - w
// left pad half, right is implicit via center visual; we only left-pad like genius
left := pad / 2
return strings.Repeat(" ", left) + value
}

func colorize(enabled bool, value, codes string) string {
if !enabled || codes == "" {
return value
}
return codes + value + ansiReset
}

func writeDetail(out *strings.Builder, withColor bool, label, value, valueColor string) {
const labelWidth = 12
if withColor {
// labels in forest (subtle earth), values in cream/brown accent
out.WriteString(colorize(true, fmt.Sprintf(" %-12s", label), ansiForest))
out.WriteString(" ")
out.WriteString(colorize(true, value, valueColor))
out.WriteByte('\n')
return
}
fmt.Fprintf(out, " %-12s %s\n", label, value)
// detailLabelWidth fits the longest detail label ("Platform") so values align.
const detailLabelWidth = 8

// writeDetail writes one detail row; value is already colourized by the caller.
func writeDetail(out *strings.Builder, withColor bool, label, value string) {
// labels in forest (subtle earth), values in cream/brown accent
padded := colorize(withColor, fmt.Sprintf("%-*s", detailLabelWidth, label), ansiForest)
fmt.Fprintf(out, "%s %s\n", padded, value)
}
3 changes: 2 additions & 1 deletion internal/welcome/welcome.xdocs.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ description: Beautiful hello window rendering for the xdocs CLI with earth-tone
parent: xdocs-internal
children: []
files:
welcome.go: ANSI earth-tone rendering (7F5539, A68A64, EDE0D4, 656D4A, 414833), XDOCS block logo, centered tagline, organization/platform/version details, and two blank lines before and after the hello window.
welcome.go: ANSI earth-tone rendering (7F5539, A68A64, EDE0D4, 656D4A, 414833), XDOCS block logo, left-aligned tagline and author line, column-0 Platform/Version/Author details with aligned values, and one blank line before and after the hello window.
welcome_test.go: Exact left-aligned plain layout and coloured-output alignment regression tests, including absence of the organization line and one-blank-line framing.
documents: {}
tags:
- welcome
Expand Down
46 changes: 46 additions & 0 deletions internal/welcome/welcome_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package welcome

import (
"strings"
"testing"
)

func TestRenderIsLeftAlignedWithoutCreatorLine(t *testing.T) {
got := Render("linux", "amd64", "0.12.0")
want := "\n" + strings.Join(xdocsLogo, "\n") + "\n" +
"Structured documentation for codebases and AI agents\n" +
"GUIHO · Cristóvão GUIHO\n" +
"\n" +
"Platform Linux x64\n" +
"Version v0.12.0\n" +
"Author GUIHO (www.guiho.co)\n" +
"\n" +
"Run xdocs --help to see available commands.\n" +
"\n"
if got != want {
t.Fatalf("unexpected welcome layout:\ngot:\n%q\nwant:\n%q", got, want)
}
}

func TestRenderWithColorKeepsLeftAlignment(t *testing.T) {
got := RenderWithColor("windows", "arm64", "v1.2.3", true)
for _, line := range strings.Split(got, "\n") {
if strings.HasPrefix(line, " ") {
t.Fatalf("coloured welcome line is indented: %q", line)
}
}
for _, required := range []string{
logoColors[0] + xdocsLogo[0] + ansiReset + "\n",
ansiSage + "GUIHO · Cristóvão GUIHO" + ansiReset + "\n\n" + ansiForest + "Platform" + ansiReset,
ansiForest + "Version " + ansiReset + " " + ansiBrown + ansiBold + "v1.2.3" + ansiReset + "\n" +
ansiForest + "Author " + ansiReset + " " +
ansiCream + "GUIHO (" + ansiReset + ansiAccent + "www.guiho.co" + ansiReset + ansiCream + ")" + ansiReset + "\n\nRun ",
} {
if !strings.Contains(got, required) {
t.Fatalf("coloured welcome omits %q:\n%q", required, got)
}
}
if strings.Contains(got, "organization") {
t.Fatalf("coloured welcome still shows the organization line: %q", got)
}
}