feat: add motd-assist TUI for managing dynamic MOTDs

Initial Go project built with Bubble Tea and Lip Gloss:
- Live preview and management of /etc/update-motd.d scripts
- Embedded presets (ubuntu-default, minimal, server-dashboard)
- Bundled POSIX sh style scripts (brand header, sysinfo panel, footer)
- Snapshot/restore safety around applying changes
- CLI subcommands preview, apply, restore, list-presets
- Unit tests for detect, sanitize, and apply logic
This commit is contained in:
Tronax 2026-08-24 14:19:28 +02:00
commit d56659e21a
Signed by: Tronax
SSH key fingerprint: SHA256:2pKKXDZucWvaF/GzXNz0FY53EAO1YDLN80bqS+TTz/o
34 changed files with 3260 additions and 0 deletions

56
internal/ui/styles.go Normal file
View file

@ -0,0 +1,56 @@
package ui
import "github.com/charmbracelet/lipgloss"
var (
colorAccent = lipgloss.Color("75")
colorBright = lipgloss.Color("81")
colorGood = lipgloss.Color("114")
colorWarn = lipgloss.Color("214")
colorBad = lipgloss.Color("203")
colorDim = lipgloss.Color("244")
colorBorder = lipgloss.Color("240")
focusedTitle = lipgloss.NewStyle().Bold(true).Foreground(colorBright)
dimStyle = lipgloss.NewStyle().Foreground(colorDim)
goodStyle = lipgloss.NewStyle().Foreground(colorGood)
badStyle = lipgloss.NewStyle().Foreground(colorBad)
warnStyle = lipgloss.NewStyle().Foreground(colorWarn)
cursorStyle = lipgloss.NewStyle().Bold(true).Foreground(colorBright)
helpStyle = lipgloss.NewStyle().Foreground(colorDim)
)
// paneBox baut den Rahmen-Stil für ein Pane mit gegebener Außenbreite/-höhe.
// lipgloss zählt Padding zur Breite, den Rahmen nicht daher w-2/h-2.
func paneBox(focused bool, w, h int) lipgloss.Style {
s := lipgloss.NewStyle().
Border(lipgloss.RoundedBorder()).
BorderForeground(colorBorder).
PaddingLeft(1).
PaddingRight(1)
if focused {
s = s.BorderForeground(colorAccent)
}
if w > 0 {
s = s.Width(w - 2)
}
if h > 0 {
s = s.Height(h - 2)
}
return s
}
// truncate schneidet s Anzeigebreite auf w und hängt … an.
func truncate(s string, w int) string {
if w <= 0 {
return ""
}
r := []rune(s)
if len(r) <= w {
return s
}
if w == 1 {
return "…"
}
return string(r[:w-1]) + "…"
}