package tui import ( "fmt" "hosts-go/internal/core" "strings" list "github.com/charmbracelet/bubbles/list" viewport "github.com/charmbracelet/bubbles/viewport" tea "github.com/charmbracelet/bubbletea" ) // entryItem wraps a HostEntry for display in a list component. type entryItem struct{ entry *core.HostEntry } func (e entryItem) Title() string { prefix := "[ ]" if e.entry.Active { prefix = "[✓]" } return fmt.Sprintf("%s %s", prefix, e.entry.Hostname) } func (e entryItem) Description() string { return e.entry.IP } func (e entryItem) FilterValue() string { return e.entry.Hostname } // Model is the main Bubble Tea model for the application. type Mode int const ( ViewMode Mode = iota EditMode ) type pane int const ( listPane pane = iota detailPane ) type Model struct { list list.Model detail viewport.Model hosts *core.HostsFile width int height int mode Mode focus pane } // NewModel constructs the TUI model from a parsed HostsFile. func NewModel(hf *core.HostsFile) Model { items := make([]list.Item, len(hf.Entries)) for i, e := range hf.Entries { items[i] = entryItem{entry: e} } l := list.New(items, list.NewDefaultDelegate(), 0, 0) l.SetShowStatusBar(false) l.SetFilteringEnabled(false) l.SetShowHelp(false) l.SetShowPagination(false) m := Model{ list: l, detail: viewport.New(0, 0), hosts: hf, mode: ViewMode, focus: listPane, } m.refreshDetail() return m } func (m *Model) refreshDetail() { if len(m.hosts.Entries) == 0 { m.detail.SetContent("") return } entry := m.hosts.Entries[m.list.Index()] var b strings.Builder status := "active" if !entry.Active { status = "inactive" } fmt.Fprintf(&b, "IP: %s\n", entry.IP) fmt.Fprintf(&b, "Host: %s\n", entry.Hostname) if len(entry.Aliases) > 0 { fmt.Fprintf(&b, "Aliases: %s\n", strings.Join(entry.Aliases, ", ")) } if entry.Comment != "" { fmt.Fprintf(&b, "Comment: %s\n", entry.Comment) } fmt.Fprintf(&b, "Status: %s", status) m.detail.SetContent(b.String()) m.detail.YOffset = 0 } // Init satisfies tea.Model. func (m Model) Init() tea.Cmd { return nil } // SelectedEntry returns the currently selected host entry. func (m Model) SelectedEntry() *core.HostEntry { if len(m.hosts.Entries) == 0 { return nil } idx := m.list.Index() if idx < 0 || idx >= len(m.hosts.Entries) { return nil } return m.hosts.Entries[idx] } // Mode returns the current operating mode of the TUI. func (m Model) Mode() Mode { return m.mode }