diff options
Diffstat (limited to 'internal/tui/help.go')
| -rw-r--r-- | internal/tui/help.go | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/internal/tui/help.go b/internal/tui/help.go new file mode 100644 index 0000000..db8d9b2 --- /dev/null +++ b/internal/tui/help.go @@ -0,0 +1,145 @@ +package tui + +import ( + "fmt" + "strings" + + common "ior/internal/tui/common" + + "charm.land/bubbles/v2/key" + "charm.land/lipgloss/v2" +) + +func renderHelpOverlay(width, height int, groups [][]key.Binding) string { + if width <= 0 { + width = 80 + } + if height <= 0 { + height = 24 + } + + lines := []string{"Help"} + for _, group := range groups { + parts := make([]string, 0, len(group)) + for _, binding := range group { + h := binding.Help() + parts = append(parts, fmt.Sprintf("%s %s", h.Key, h.Desc)) + } + lines = append(lines, strings.Join(parts, " • ")) + } + lines = append(lines, "", "Esc/?/q close") + + boxWidth := width - 6 + if boxWidth < 72 { + boxWidth = 72 + } + + box := common.PanelStyle.Copy(). + Width(boxWidth). + Render(strings.Join(lines, "\n")) + + return lipgloss.Place(width, height, lipgloss.Center, lipgloss.Center, box) +} + +type helpSection struct { + title string + lines []string +} + +func (m Model) helpSections() []helpSection { + globalLines := []string{ + "H help esc/? close help q quit", + "f filter p pid picker t tid picker o probes", + } + if help := m.keys.Export.Help(); help.Key != "" || help.Desc != "" { + globalLines[1] += " e stream export" + } + + return []helpSection{ + { + title: "Global", + lines: globalLines, + }, + { + title: "Dashboard Tabs", + lines: []string{ + "tab/shift+tab tabs 1..7 jump tab r reset baseline", + "sys/files/proc/stream tables: arrows or hjkl move pgup/pgdown page g/G top/bottom", + "sys/files/proc tables: s sort S reverse sort", + "sys/proc: v bubbles b metric events/bytes", + "files: d dirs toggle v bubbles (dirs only) b metric", + "flame: arrows/hjkl nav enter/click zoom click ancestor undo u/bs/esc undo o order", + "flame: / filter n/N match next/prev space pause b metric", + "stream: space pause enter push filter esc/F undo /? n/N search", + "stream: x/X export E open", + }, + }, + { + title: "PID/TID Picker", + lines: []string{ + "enter select r refresh esc/q back", + }, + }, + } +} + +func renderGlobalHelpOverlay(width, height int, sections []helpSection) string { + if width <= 0 { + width = 80 + } + if height <= 0 { + height = 24 + } + + boxWidth := width - 4 + if boxWidth > 100 { + boxWidth = 100 + } + if boxWidth < 74 { + boxWidth = 74 + } + contentWidth := boxWidth - 4 + if contentWidth < 20 { + contentWidth = boxWidth + } + + lines := make([]string, 0, 24) + lines = append(lines, "Help") + for _, section := range sections { + lines = append(lines, "") + lines = append(lines, section.title) + for _, line := range section.lines { + lines = append(lines, " "+truncateHelpLine(line, contentWidth-2)) + } + } + lines = append(lines, "", "Esc/q close") + + maxLines := height - 4 + if maxLines < 6 { + maxLines = 6 + } + if len(lines) > maxLines { + lines = lines[:maxLines-1] + lines = append(lines, truncateHelpLine("... (resize for full help)", contentWidth)) + } + + box := common.PanelStyle.Copy().Width(boxWidth).Render(strings.Join(lines, "\n")) + return lipgloss.Place(width, height, lipgloss.Center, lipgloss.Center, box) +} + +func truncateHelpLine(s string, width int) string { + if width <= 0 { + return "" + } + if lipgloss.Width(s) <= width { + return s + } + if width == 1 { + return "…" + } + r := []rune(s) + if len(r) >= width { + return string(r[:width-1]) + "…" + } + return s +} |
