diff --git a/cmd/kctl-tui/full.go b/cmd/kctl-tui/full.go index 1ecdd6e..a28500a 100644 --- a/cmd/kctl-tui/full.go +++ b/cmd/kctl-tui/full.go @@ -47,7 +47,7 @@ type fullModel struct { } func newFullModel() *fullModel { - l := list.New(nil, list.NewDefaultDelegate(), 0, 0) + l := list.New(nil, newCompactDelegate(), 0, 0) l.Title = "kctl-tui" l.SetShowStatusBar(false) l.SetFilteringEnabled(false) @@ -210,23 +210,21 @@ func (m *fullModel) handleSelect() (tea.Model, tea.Cmd) { return m, nil } -// bootstrapContext resolves a kubectl context purely to discover -// namespaces/labels for the team/namespace screens. The first configured -// env is used as a stable default for this discovery step, since -// namespace names are assumed to be identical across envs. -func (m *fullModel) bootstrapContext() string { - if len(m.cfg.Envs) == 0 { - return "" - } - return m.cfg.ResolveContext(m.cfg.Envs[0], m.selectedContext) -} - func (m *fullModel) loadTeams() tea.Msg { - namespaces, err := kubeexec.GetNamespacesWithLabels(m.bootstrapContext()) - if err != nil { - return errMsg{err} + merged := map[string]map[string]string{} + for _, env := range m.cfg.Envs { + ctx := m.cfg.ResolveContext(env, m.selectedContext) + namespaces, err := kubeexec.GetNamespacesWithLabels(ctx) + if err != nil { + continue + } + for ns, labels := range namespaces { + if _, exists := merged[ns]; !exists { + merged[ns] = labels + } + } } - return *toTeamsLoadedMsg(namespaces, m.cfg.TeamLabelKey) + return *toTeamsLoadedMsg(merged, m.cfg.TeamLabelKey) } func (m *fullModel) loadTeamsFor(namespaces map[string]map[string]string) tea.Cmd { diff --git a/cmd/kctl-tui/list_item.go b/cmd/kctl-tui/list_item.go index f986493..fd01faa 100644 --- a/cmd/kctl-tui/list_item.go +++ b/cmd/kctl-tui/list_item.go @@ -3,6 +3,8 @@ package main +import "github.com/charmbracelet/bubbles/list" + // simpleItem is a minimal implementation of list.Item used for all // selection screens (contexts, teams, namespaces, menu actions). type simpleItem struct { @@ -13,3 +15,13 @@ type simpleItem struct { func (i simpleItem) Title() string { return i.label } func (i simpleItem) Description() string { return "" } func (i simpleItem) FilterValue() string { return i.label } + +// newCompactDelegate returns a list delegate that renders each item as a +// single line with no extra spacing, maximizing the number of visible +// entries in the terminal. +func newCompactDelegate() list.DefaultDelegate { + d := list.NewDefaultDelegate() + d.ShowDescription = false + d.SetSpacing(0) + return d +} diff --git a/cmd/kctl-tui/panel.go b/cmd/kctl-tui/panel.go index 32dc6a7..e2640b7 100644 --- a/cmd/kctl-tui/panel.go +++ b/cmd/kctl-tui/panel.go @@ -83,7 +83,7 @@ func newPanelModel(context, ns, team string) *panelModel { cfgPath, _ := config.DefaultPath() cfg, loadErr := config.Load(cfgPath) - l := list.New(nil, list.NewDefaultDelegate(), 0, 0) + l := list.New(nil, newCompactDelegate(), 0, 0) l.SetShowStatusBar(false) l.SetFilteringEnabled(false)