Files
bbs-server/engine/menu.go
2026-03-11 21:14:56 +01:00

79 lines
2.3 KiB
Go

package engine
import (
"fmt"
"strings"
)
// HandlerFunc is the handler type for a menu item
type HandlerFunc func(*Session)
// Exit is a built-in handler that terminates the session
var Exit HandlerFunc = func(s *Session) { s.Quit = true }
type menuItem struct {
Key string
Label string
Color string
Handler HandlerFunc
}
// Menu defines the BBS main menu using a declarative DSL
type Menu struct {
title string
items []menuItem
}
// Title sets the menu header
func (m *Menu) Title(t string) {
m.title = t
}
// Item adds a menu entry (key, display label, ANSI color, handler)
func (m *Menu) Item(key, label, color string, handler HandlerFunc) {
m.items = append(m.items, menuItem{
Key: strings.ToUpper(key),
Label: label,
Color: color,
Handler: handler,
})
}
// Dispatch finds and calls the handler for the given key
func (m *Menu) Dispatch(s *Session, key string) {
key = strings.ToUpper(strings.TrimSpace(key))
for _, item := range m.items {
if item.Key == key {
item.Handler(s)
return
}
}
}
// Render returns the rendered menu string
func (m *Menu) Render(p *Printer, lang T, username string) string {
headerLine := strings.Repeat("═", W)
l1 := p.PadLine(fmt.Sprintf(" %s%s%s %s@%s%s", COLOR_YELLOW, m.title, COLOR_RESET, COLOR_GRAY, username, COLOR_RESET), W)
var rows []string
for i := 0; i < len(m.items); i += 2 {
if i+1 < len(m.items) {
left := p.PadLine(fmt.Sprintf(" %s[%s]%s %s", m.items[i].Color, m.items[i].Key, COLOR_RESET, m.items[i].Label), W/2)
right := p.PadLine(fmt.Sprintf(" %s[%s]%s %s", m.items[i+1].Color, m.items[i+1].Key, COLOR_RESET, m.items[i+1].Label), W/2)
rows = append(rows, left+right)
} else {
rows = append(rows, p.PadLine(fmt.Sprintf(" %s[%s]%s %s", m.items[i].Color, m.items[i].Key, COLOR_RESET, m.items[i].Label), W))
}
}
var sb strings.Builder
sb.WriteString(fmt.Sprintf("\n%s╔%s╗%s\n", COLOR_WHITE, headerLine, COLOR_RESET))
sb.WriteString(fmt.Sprintf("%s║%s%s║%s\n", COLOR_WHITE, l1, COLOR_WHITE, COLOR_RESET))
sb.WriteString(fmt.Sprintf("%s╠%s╣%s\n", COLOR_WHITE, headerLine, COLOR_RESET))
for _, row := range rows {
sb.WriteString(fmt.Sprintf("%s║%s%s║%s\n", COLOR_WHITE, row, COLOR_WHITE, COLOR_RESET))
}
sb.WriteString(fmt.Sprintf("%s╚%s╝%s\n%s", COLOR_WHITE, headerLine, COLOR_RESET, lang["Choice"]))
return sb.String()
}