Skip to content

Commit 6ca205f

Browse files
Merge pull request #11 from miguelmartens/fix/text-alignment
Refactor custom view and settings display in app.go to improve layout…
2 parents 6f3401f + 160b324 commit 6ca205f

1 file changed

Lines changed: 52 additions & 8 deletions

File tree

internal/ui/app.go

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/cowardly/cowardly/internal/brave"
1212
"github.com/cowardly/cowardly/internal/config"
1313
"github.com/cowardly/cowardly/internal/presets"
14+
"github.com/mattn/go-runewidth"
1415
)
1516

1617
type applyPresetMsg struct{ idx int }
@@ -405,15 +406,19 @@ func (m model) View() string {
405406
func (m model) customView() string {
406407
var b strings.Builder
407408
b.WriteString(titleStyle.Render("Custom — Toggle settings (Space), Apply (Enter)"))
408-
b.WriteString(dimStyle.Render("\n[a] select all [n] select none [esc] back\n\n"))
409+
b.WriteString("\n")
410+
b.WriteString(dimStyle.Render("[a] select all [n] select none [esc] back"))
411+
b.WriteString("\n\n") // raw newlines so the next line is not inside any style
409412

413+
// Inline(true) prevents block-level reflow so the category stays at column 0
414+
catStyle := lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("#ff631c")).Inline(true)
410415
byCat := config.CustomSettingsByCategory()
411416
for _, cat := range config.CategoryOrder {
412417
idxs, ok := byCat[cat]
413418
if !ok || len(idxs) == 0 {
414419
continue
415420
}
416-
b.WriteString(lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("#ff631c")).Render(cat))
421+
b.WriteString(catStyle.Render(cat))
417422
b.WriteString("\n")
418423
for _, i := range idxs {
419424
cs := m.customSettings[i]
@@ -435,21 +440,60 @@ func (m model) customView() string {
435440
}
436441

437442
func (m model) viewSettingsView() string {
438-
headerStyle := lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("#ff631c"))
443+
headerStyle := lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("#ff631c")).Inline(true)
439444
var b strings.Builder
440445
b.WriteString(headerStyle.Render("Current Brave settings"))
441-
b.WriteString(dimStyle.Render("\n(managed overrides user; enforced = what Brave uses)\n\n"))
446+
b.WriteString("\n")
447+
b.WriteString(dimStyle.Render("(managed overrides user; enforced = what Brave uses)"))
448+
b.WriteString("\n\n") // raw newlines so the list is not inside any style
449+
// Inline styles so each line stays at column 0 (no block reflow)
450+
checkIconStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("#4caf50")).Inline(true)
451+
unsetIconStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("241")).Inline(true)
452+
maxKeyWidth := 0
453+
for _, key := range m.viewKeys {
454+
if w := runewidth.StringWidth(key); w > maxKeyWidth {
455+
maxKeyWidth = w
456+
}
457+
}
458+
prefixRaw := " ✓ " // unstyled for width calculation
442459
for _, key := range m.viewKeys {
443460
managedVal, managedOK := brave.ReadManaged(key)
444461
userVal, userOK := brave.Read(key)
462+
paddedKey := key + strings.Repeat(" ", maxKeyWidth-runewidth.StringWidth(key))
463+
var valuePart, suffix string
464+
var line string
445465
if managedOK {
446-
b.WriteString(" " + checkStyle.Render("✓ ") + key + " = " + managedVal + " (enforced)\n")
466+
valuePart = managedVal
467+
suffix = " (enforced)"
468+
line = " " + checkIconStyle.Render("✓ ") + paddedKey + " = " + managedVal + suffix + "\n"
447469
} else if userOK {
448-
b.WriteString(" " + checkStyle.Render("✓ ") + key + " = " + userVal + " (user)\n")
470+
valuePart = userVal
471+
suffix = " (user)"
472+
line = " " + checkIconStyle.Render("✓ ") + paddedKey + " = " + userVal + suffix + "\n"
473+
} else {
474+
valuePart = "(not set)"
475+
suffix = ""
476+
line = " " + unsetIconStyle.Render("○ ") + paddedKey + " = (not set)\n"
477+
}
478+
// When line would wrap, break so "= value (enforced)" aligns in a column
479+
lineWidth := runewidth.StringWidth(prefixRaw+paddedKey) + runewidth.StringWidth(" = "+valuePart+suffix)
480+
if m.width > 0 && lineWidth > m.width {
481+
indent := runewidth.StringWidth(prefixRaw + paddedKey)
482+
if managedOK {
483+
b.WriteString(" " + checkIconStyle.Render("✓ ") + paddedKey + "\n")
484+
b.WriteString(strings.Repeat(" ", indent) + "= " + managedVal + " (enforced)\n")
485+
} else if userOK {
486+
b.WriteString(" " + checkIconStyle.Render("✓ ") + paddedKey + "\n")
487+
b.WriteString(strings.Repeat(" ", indent) + "= " + userVal + " (user)\n")
488+
} else {
489+
b.WriteString(" " + unsetIconStyle.Render("○ ") + paddedKey + "\n")
490+
b.WriteString(strings.Repeat(" ", indent) + "= (not set)\n")
491+
}
449492
} else {
450-
b.WriteString(" " + dimStyle.Render("○ ") + key + " = (not set)\n")
493+
b.WriteString(line)
451494
}
452495
}
453-
b.WriteString(dimStyle.Render("\nq/esc back"))
496+
b.WriteString("\n")
497+
b.WriteString(dimStyle.Render("q/esc back"))
454498
return b.String()
455499
}

0 commit comments

Comments
 (0)