Merge pull request '[agent/codex:gpt-5.4-mini] Read ~/spec/code/core/go/cli/RFC.md fully. Find features des...' (#64) from agent/read---spec-code-core-go-cli-rfc-md-full into dev
All checks were successful
Security Scan / security (push) Successful in 23s

This commit is contained in:
Virgil 2026-04-02 10:07:50 +00:00
commit 6c39c0f932
6 changed files with 65 additions and 15 deletions

View file

@ -64,23 +64,24 @@ func (c *CheckBuilder) Message(msg string) *CheckBuilder {
// String returns the formatted check line. // String returns the formatted check line.
func (c *CheckBuilder) String() string { func (c *CheckBuilder) String() string {
icon := c.icon icon := compileGlyphs(c.icon)
if c.style != nil { if c.style != nil {
icon = c.style.Render(c.icon) icon = c.style.Render(icon)
} }
status := c.status status := compileGlyphs(c.status)
if c.style != nil && c.status != "" { if c.style != nil && c.status != "" {
status = c.style.Render(c.status) status = c.style.Render(status)
} }
name := compileGlyphs(c.name)
if c.duration != "" { if c.duration != "" {
return Sprintf(" %s %-20s %-10s %s", icon, c.name, status, DimStyle.Render(c.duration)) return Sprintf(" %s %-20s %-10s %s", icon, name, status, DimStyle.Render(compileGlyphs(c.duration)))
} }
if status != "" { if status != "" {
return Sprintf(" %s %s %s", icon, c.name, status) return Sprintf(" %s %s %s", icon, name, status)
} }
return Sprintf(" %s %s", icon, c.name) return Sprintf(" %s %s", icon, name)
} }
// Print outputs the check result. // Print outputs the check result.

View file

@ -1,6 +1,9 @@
package cli package cli
import "testing" import (
"strings"
"testing"
)
func TestCheckBuilder(t *testing.T) { func TestCheckBuilder(t *testing.T) {
restoreThemeAndColors(t) restoreThemeAndColors(t)
@ -47,4 +50,17 @@ func TestCheckBuilder(t *testing.T) {
if got == "" { if got == "" {
t.Error("Empty output for Message") t.Error("Empty output for Message")
} }
// Glyph shortcodes
c = Check(":check: foo").Warn().Message(":warn:")
got = c.String()
if got == "" {
t.Error("Empty output for glyph shortcode rendering")
}
if !strings.Contains(got, "[OK] foo") {
t.Error("Expected shortcode-rendered name")
}
if strings.Count(got, "[WARN]") < 2 {
t.Error("Expected shortcode-rendered warning icon and message")
}
} }

View file

@ -20,9 +20,9 @@ func StatusLine(title string, pairs ...string) Model {
} }
func (s *statusLineModel) View(width, _ int) string { func (s *statusLineModel) View(width, _ int) string {
parts := []string{BoldStyle.Render(s.title)} parts := []string{BoldStyle.Render(compileGlyphs(s.title))}
for _, p := range s.pairs { for _, p := range s.pairs {
parts = append(parts, DimStyle.Render(p)) parts = append(parts, DimStyle.Render(compileGlyphs(p)))
} }
line := strings.Join(parts, " ") line := strings.Join(parts, " ")
if width > 0 { if width > 0 {
@ -46,7 +46,7 @@ func KeyHints(hints ...string) Model {
func (k *keyHintsModel) View(width, _ int) string { func (k *keyHintsModel) View(width, _ int) string {
parts := make([]string, len(k.hints)) parts := make([]string, len(k.hints))
for i, h := range k.hints { for i, h := range k.hints {
parts[i] = DimStyle.Render(h) parts[i] = DimStyle.Render(compileGlyphs(h))
} }
line := strings.Join(parts, " ") line := strings.Join(parts, " ")
if width > 0 { if width > 0 {
@ -70,10 +70,11 @@ func Breadcrumb(parts ...string) Model {
func (b *breadcrumbModel) View(width, _ int) string { func (b *breadcrumbModel) View(width, _ int) string {
styled := make([]string, len(b.parts)) styled := make([]string, len(b.parts))
for i, p := range b.parts { for i, p := range b.parts {
part := compileGlyphs(p)
if i == len(b.parts)-1 { if i == len(b.parts)-1 {
styled[i] = BoldStyle.Render(p) styled[i] = BoldStyle.Render(part)
} else { } else {
styled[i] = DimStyle.Render(p) styled[i] = DimStyle.Render(part)
} }
} }
line := strings.Join(styled, DimStyle.Render(" > ")) line := strings.Join(styled, DimStyle.Render(" > "))

View file

@ -207,6 +207,25 @@ func TestBreadcrumb_Good(t *testing.T) {
assert.Contains(t, out, ">") assert.Contains(t, out, ">")
} }
func TestFrameComponents_GlyphShortcodes(t *testing.T) {
restoreThemeAndColors(t)
UseASCII()
status := StatusLine(":check: core", ":warn: repos")
assert.Contains(t, status.View(80, 1), "[OK] core")
assert.Contains(t, status.View(80, 1), "[WARN] repos")
hints := KeyHints(":info: help", ":cross: quit")
hintsOut := hints.View(80, 1)
assert.Contains(t, hintsOut, "[INFO] help")
assert.Contains(t, hintsOut, "[FAIL] quit")
breadcrumb := Breadcrumb(":check: core", "dev", ":warn: health")
breadcrumbOut := breadcrumb.View(80, 1)
assert.Contains(t, breadcrumbOut, "[OK] core")
assert.Contains(t, breadcrumbOut, "[WARN] health")
}
func TestStaticModel_Good(t *testing.T) { func TestStaticModel_Good(t *testing.T) {
m := StaticModel("hello") m := StaticModel("hello")
assert.Equal(t, "hello", m.View(80, 24)) assert.Equal(t, "hello", m.View(80, 24))

View file

@ -83,10 +83,11 @@ func (n *TreeNode) Render() {
} }
func (n *TreeNode) renderLabel() string { func (n *TreeNode) renderLabel() string {
label := compileGlyphs(n.label)
if n.style != nil { if n.style != nil {
return n.style.Render(n.label) return n.style.Render(label)
} }
return n.label return label
} }
func (n *TreeNode) writeChildren(sb *strings.Builder, prefix string) { func (n *TreeNode) writeChildren(sb *strings.Builder, prefix string) {

View file

@ -125,6 +125,18 @@ func TestTree_Good(t *testing.T) {
"`-- core-api\n" "`-- core-api\n"
assert.Equal(t, expected, tree.String()) assert.Equal(t, expected, tree.String())
}) })
t.Run("glyph shortcodes render in labels", func(t *testing.T) {
restoreThemeAndColors(t)
UseASCII()
tree := NewTree(":check: root")
tree.Add(":warn: child")
out := tree.String()
assert.Contains(t, out, "[OK] root")
assert.Contains(t, out, "[WARN] child")
})
} }
func TestTree_Bad(t *testing.T) { func TestTree_Bad(t *testing.T) {