mirror of
https://github.com/shokinn/hosts-go.git
synced 2025-08-23 08:33:02 +00:00
feat: begin tui implementation
This commit is contained in:
parent
b81f11f711
commit
1b66db10e2
9 changed files with 200 additions and 154 deletions
57
internal/tui/model.go
Normal file
57
internal/tui/model.go
Normal file
|
@ -0,0 +1,57 @@
|
|||
package tui
|
||||
|
||||
import (
|
||||
"hosts-go/internal/core"
|
||||
|
||||
list "github.com/charmbracelet/bubbles/list"
|
||||
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 { return 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 Model struct {
|
||||
list list.Model
|
||||
hosts *core.HostsFile
|
||||
width int
|
||||
height int
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
||||
return Model{
|
||||
list: l,
|
||||
hosts: hf,
|
||||
}
|
||||
}
|
||||
|
||||
// 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]
|
||||
}
|
24
internal/tui/update.go
Normal file
24
internal/tui/update.go
Normal file
|
@ -0,0 +1,24 @@
|
|||
package tui
|
||||
|
||||
import (
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
)
|
||||
|
||||
// Update handles all messages for the TUI.
|
||||
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
var cmd tea.Cmd
|
||||
switch msg := msg.(type) {
|
||||
case tea.KeyMsg:
|
||||
switch msg.String() {
|
||||
case "q", "ctrl+c":
|
||||
return m, tea.Quit
|
||||
}
|
||||
case tea.WindowSizeMsg:
|
||||
m.width = msg.Width
|
||||
m.height = msg.Height
|
||||
m.list.SetSize(msg.Width/2, msg.Height)
|
||||
}
|
||||
|
||||
m.list, cmd = m.list.Update(msg)
|
||||
return m, cmd
|
||||
}
|
40
internal/tui/view.go
Normal file
40
internal/tui/view.go
Normal file
|
@ -0,0 +1,40 @@
|
|||
package tui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
)
|
||||
|
||||
var (
|
||||
listStyle = lipgloss.NewStyle().Padding(0, 1)
|
||||
detailStyle = lipgloss.NewStyle().Padding(0, 1)
|
||||
)
|
||||
|
||||
// View renders the two-pane layout.
|
||||
func (m Model) View() string {
|
||||
listView := m.list.View()
|
||||
|
||||
var detail strings.Builder
|
||||
if len(m.hosts.Entries) > 0 {
|
||||
entry := m.hosts.Entries[m.list.Index()]
|
||||
status := "active"
|
||||
if !entry.Active {
|
||||
status = "inactive"
|
||||
}
|
||||
fmt.Fprintf(&detail, "IP: %s\n", entry.IP)
|
||||
fmt.Fprintf(&detail, "Host: %s\n", entry.Hostname)
|
||||
if len(entry.Aliases) > 0 {
|
||||
fmt.Fprintf(&detail, "Aliases: %s\n", strings.Join(entry.Aliases, ", "))
|
||||
}
|
||||
if entry.Comment != "" {
|
||||
fmt.Fprintf(&detail, "Comment: %s\n", entry.Comment)
|
||||
}
|
||||
fmt.Fprintf(&detail, "Status: %s", status)
|
||||
}
|
||||
|
||||
left := listStyle.Width(m.width / 2).Height(m.height).Render(listView)
|
||||
right := detailStyle.Width(m.width - m.width/2).Height(m.height).Render(detail.String())
|
||||
return lipgloss.JoinHorizontal(lipgloss.Top, left, right)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue