mirror of
https://github.com/shokinn/hosts-go.git
synced 2025-08-23 08:33:02 +00:00
113 lines
2.3 KiB
Go
113 lines
2.3 KiB
Go
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]
|
|
}
|