[#1223] lens/tui: Enchance help page

- Make help multipage: one page for each chapter.
- Improve help information.
- Add markup.

Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
This commit is contained in:
Aleksey Savchuk 2024-08-12 15:25:24 +03:00
parent ff28b7e592
commit 4ed3b273f9
No known key found for this signature in database
5 changed files with 119 additions and 49 deletions

View file

@ -0,0 +1 @@
[green::b]Development[white::-] (Work in Progress)

View file

@ -0,0 +1,27 @@
[green::b]General Navigation[white::-]
[yellow::b]Down Arrow[white::-] / [yellow::b]j[white::-]
Scroll down.
[yellow::b]Up Arrow[white::-] / [yellow::b]k[white::-]
Scroll up.
[yellow::b]Page Down[white::-] / [yellow::b]Ctrl-f[white::-]
Scroll down by a full page.
[yellow::b]Page Up[white::-] / [yellow::b]Ctrl-b[white::-]
Scroll up by a full page.
[yellow::b]Enter[white::-]
Navigate to a nested view:
- In Buckets View: Navigate to the selected bucket's records.
- In Records View: Navigate to the selected record's detailed view.
[yellow::b]Escape[white::-]
Return to the previous page, opposite of [yellow::b]Enter[white::-].
[green::b]Buckets View Interactions[white::-]
[yellow::b]Space[white::-]
Expand or collapse the selected bucket to show or hide its nested buckets.

View file

@ -0,0 +1,16 @@
[green::b]Searching[white::-]
[yellow::b]/[white::-]
Initiate a search prompt. Prompt syntax: [yellow::b]<tag>:<args>[white::-]. Leading and trailing white spaces are ignored. See [green::b]Available Search Filters[white::-] section for available filter tags.
[yellow::b]Enter[white::-]
Execute the search based on the entered prompt. An error message will display if the prompt is invalid.
[yellow::b]Escape[white::-]
Exit the search prompt.
[green::b]Available Search Filters[white::-]
%s
If you want to define a new filter, see [green::b]Development[white::-] section.

View file

@ -1,6 +1,7 @@
package tuiutil
import (
_ "embed"
"fmt"
"strings"
@ -8,76 +9,101 @@ import (
"github.com/rivo/tview"
)
const text = `[green]Navigation[white]
var (
//go:embed help-pages/navigation.txt
navigationHelpText string
- [yellow]Up arrow[white] Move up.
//go:embed help-pages/searching.txt
searchingHelpText string
- [yellow]Down arrow[white] Move down.
- [yellow]Space[white] Show a bucket's subbuckets if on the buckets view.
- [yellow]Enter[white] Show a bucket's records if on the buckets view,
or show a record's detailed view if on the
records view. It always navigates to a new page.
- [yellow]Escape[white] Go to the previous page.
[green]Searching[white]
- [yellow]/[white] Start search prompt.
Prompt syntax is <filter tag>:<filter args...>.
It tolerates leading and trailing white space.
- [yellow]Enter[white] Start searching based on prompt. It shows an
error message if the prompt is invalid.
- [yellow]Escape[white] Stop search prompt.
[green]Available search filters[white]
%s
`
//go:embed help-pages/development.txt
developmentHelpText string
)
type HelpPage struct {
*tview.Box
view *tview.TextView
pages []*tview.TextView
currentPage int
filters []string
filterHints map[string]string
}
func NewHelpPage(filters []string, hints map[string]string) *HelpPage {
hp := &HelpPage{
Box: tview.NewBox(),
view: tview.NewTextView(),
Box: tview.NewBox(),
filters: filters,
filterHints: hints,
}
filtersText := strings.Builder{}
page := tview.NewTextView()
page.SetDynamicColors(true)
page.SetText(navigationHelpText)
hp.addPage(page)
lastIndex := len(filters) - 1
for index, filter := range filters {
filtersText.WriteString("- ")
filtersText.WriteString(filter)
filtersText.WriteRune(' ')
filtersText.WriteString(hints[filter])
if index != lastIndex {
filtersText.WriteRune('\n')
}
}
page = tview.NewTextView()
page.SetDynamicColors(true)
page.SetText(fmt.Sprintf(searchingHelpText, hp.getFiltersText()))
hp.addPage(page)
hp.view.SetDynamicColors(true)
hp.view.SetText(fmt.Sprintf(text, filtersText.String()))
page = tview.NewTextView()
page.SetDynamicColors(true)
page.SetText(developmentHelpText)
hp.addPage(page)
return hp
}
func (hp *HelpPage) addPage(page *tview.TextView) {
hp.pages = append(hp.pages, page)
}
func (hp *HelpPage) getFiltersText() string {
if len(hp.filters) == 0 {
return "\tNo filters defined.\n"
}
filtersText := strings.Builder{}
gapSize := 4
tagMaxWidth := 3
for _, filter := range hp.filters {
tagMaxWidth = max(tagMaxWidth, len(filter))
}
filtersText.WriteString("\t[yellow::b]Tag")
filtersText.WriteString(strings.Repeat(" ", gapSize))
filtersText.WriteString("\tArgs[white::-]\n\n")
for _, filter := range hp.filters {
filtersText.WriteRune('\t')
filtersText.WriteString(filter)
filtersText.WriteString(strings.Repeat(" ", tagMaxWidth-len(filter)+gapSize))
filtersText.WriteString(hp.filterHints[filter])
filtersText.WriteRune('\n')
}
return filtersText.String()
}
func (hp *HelpPage) Draw(screen tcell.Screen) {
x, y, width, height := hp.GetInnerRect()
hp.view.SetRect(x, y, width, height)
hp.view.Draw(screen)
hp.pages[hp.currentPage].SetRect(x+1, y+1, width-2, height-2)
hp.pages[hp.currentPage].Draw(screen)
}
func (hp *HelpPage) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
return hp.WrapInputHandler(func(event *tcell.EventKey, _ func(tview.Primitive)) {
hp.view.InputHandler()(event, func(tview.Primitive) {})
if event.Key() == tcell.KeyEnter {
hp.currentPage++
hp.currentPage %= len(hp.pages)
return
}
hp.pages[hp.currentPage].InputHandler()(event, func(tview.Primitive) {})
})
}
func (hp *HelpPage) MouseHandler() func(action tview.MouseAction, event *tcell.EventMouse, setFocus func(p tview.Primitive)) (consumed bool, capture tview.Primitive) {
return hp.WrapMouseHandler(func(action tview.MouseAction, event *tcell.EventMouse, _ func(tview.Primitive)) (consumed bool, capture tview.Primitive) {
return hp.pages[hp.currentPage].MouseHandler()(action, event, func(tview.Primitive) {})
})
}

View file

@ -102,7 +102,7 @@ func NewUI(ctx context.Context, app *tview.Application, db *bbolt.DB) *UI {
ui.helpBar.SetBackgroundColor(barBackgroundColor)
ui.helpBar.SetTextColor(barTextColor)
ui.helpBar.SetText(" Press Escape to quit")
ui.helpBar.SetText(" Press Enter for next page or Escape to exit help ")
ui.searchErrorBar.SetBackgroundColor(barTextColor)
ui.searchErrorBar.SetTextColor(barAlertTextColor)