[#1223] lens/tui: Add search history
Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
This commit is contained in:
parent
c46c868628
commit
b3f8b30842
3 changed files with 93 additions and 7 deletions
|
@ -1,16 +1,18 @@
|
|||
[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.
|
||||
Initiate the search prompt. The prompt follows this syntax: [yellow::b]<tag>:<args>[white::-]. Any leading and trailing whitespace will be ignored. Refer to the [green::b]Available Search Filters[white::-] section below for a list of valid filter tags.
|
||||
|
||||
[yellow::b]Enter[white::-]
|
||||
Execute the search based on the entered prompt. An error message will display if the prompt is invalid.
|
||||
Execute the search based on the entered prompt. If the prompt is invalid, an error message will be displayed.
|
||||
|
||||
[yellow::b]Escape[white::-]
|
||||
Exit the search prompt.
|
||||
Exit the search prompt without performing a search.
|
||||
|
||||
[yellow::b]Down Arrow[white::-], [yellow::b]Up Arrow[white::-]
|
||||
Navigate through the search history.
|
||||
|
||||
[green::b]Available Search Filters[white::-]
|
||||
|
||||
%s
|
||||
If you want to define a new filter, see [green::b]Development[white::-] section.
|
||||
To define a new filter, please refer to the [green::b]Development[white::-] section.
|
||||
|
|
79
cmd/frostfs-lens/internal/tuiutil/input.go
Normal file
79
cmd/frostfs-lens/internal/tuiutil/input.go
Normal file
|
@ -0,0 +1,79 @@
|
|||
package tuiutil
|
||||
|
||||
import (
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
type InputFieldWithHistory struct {
|
||||
*tview.InputField
|
||||
history []string
|
||||
historyLimit int
|
||||
historyPointer int
|
||||
currentContent string
|
||||
}
|
||||
|
||||
func NewInputFieldWithHistory(historyLimit int) *InputFieldWithHistory {
|
||||
return &InputFieldWithHistory{
|
||||
InputField: tview.NewInputField(),
|
||||
historyLimit: historyLimit,
|
||||
}
|
||||
}
|
||||
|
||||
func (f *InputFieldWithHistory) AddToHistory(s string) *InputFieldWithHistory {
|
||||
defer func() { f.historyPointer = len(f.history) }()
|
||||
|
||||
// Used history for search prompt
|
||||
if f.historyPointer != len(f.history) && s == f.history[f.historyPointer] {
|
||||
f.history = append(f.history[:f.historyPointer], f.history[f.historyPointer+1:]...)
|
||||
f.history = append(f.history, s)
|
||||
return f
|
||||
}
|
||||
|
||||
if len(f.history) == f.historyLimit {
|
||||
f.history = f.history[1:]
|
||||
}
|
||||
f.history = append(f.history, s)
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *InputFieldWithHistory) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
|
||||
return f.WrapInputHandler(func(event *tcell.EventKey, _ func(tview.Primitive)) {
|
||||
switch event.Key() {
|
||||
case tcell.KeyDown:
|
||||
// Must start iterating before
|
||||
if f.historyPointer == len(f.history) {
|
||||
return
|
||||
}
|
||||
// Stop iterating over history.
|
||||
if f.historyPointer == len(f.history)-1 {
|
||||
f.historyPointer++
|
||||
f.InputField.SetText(f.currentContent)
|
||||
return
|
||||
}
|
||||
// Iterate back.
|
||||
f.historyPointer++
|
||||
f.InputField.SetText(f.history[f.historyPointer])
|
||||
case tcell.KeyUp:
|
||||
if len(f.history) == 0 {
|
||||
return
|
||||
}
|
||||
// Start iterating over history.
|
||||
if f.historyPointer == len(f.history) {
|
||||
f.historyPointer--
|
||||
f.currentContent = f.InputField.GetText()
|
||||
f.InputField.SetText(f.history[f.historyPointer])
|
||||
return
|
||||
}
|
||||
// End of history.
|
||||
if f.historyPointer == 0 {
|
||||
return
|
||||
}
|
||||
// Iterate forth.
|
||||
f.historyPointer--
|
||||
f.InputField.SetText(f.history[f.historyPointer])
|
||||
default:
|
||||
f.InputField.InputHandler()(event, func(tview.Primitive) {})
|
||||
}
|
||||
})
|
||||
}
|
|
@ -45,7 +45,7 @@ type UI struct {
|
|||
pageStub tview.Primitive
|
||||
|
||||
infoBar *tview.TextView
|
||||
searchBar *tview.InputField
|
||||
searchBar *InputFieldWithHistory
|
||||
loadingBar *LoadingBar
|
||||
helpBar *tview.TextView
|
||||
|
||||
|
@ -79,7 +79,7 @@ func NewUI(ctx context.Context, app *tview.Application, db *bbolt.DB) *UI {
|
|||
isFirstMount: true,
|
||||
infoBar: tview.NewTextView(),
|
||||
pageStub: tview.NewBox(),
|
||||
searchBar: tview.NewInputField(),
|
||||
searchBar: NewInputFieldWithHistory(100),
|
||||
filterHints: make(map[string]string),
|
||||
helpBar: tview.NewTextView(),
|
||||
searchErrorBar: tview.NewTextView(),
|
||||
|
@ -111,6 +111,7 @@ func NewUI(ctx context.Context, app *tview.Application, db *bbolt.DB) *UI {
|
|||
ui.pageToMount = NewBucketsView(ui, NewFilter(nil))
|
||||
|
||||
ui.searchBar.SetLabel("/")
|
||||
|
||||
ui.infoBar.SetText(fmt.Sprintf(" %s (press h for help, / to search or q to quit) ", db.Path()))
|
||||
|
||||
return ui
|
||||
|
@ -442,8 +443,12 @@ func (ui *UI) handleInputOnSearching(event *tcell.EventKey) {
|
|||
ui.moveNextPage(NewRecordsView(ui, bucket, res))
|
||||
}
|
||||
|
||||
if ui.searchBar.GetText() != "" {
|
||||
ui.searchBar.AddToHistory(ui.searchBar.GetText())
|
||||
}
|
||||
|
||||
ui.searchBar.SetText("")
|
||||
ui.isSearching = false
|
||||
// ui.searchBar.SetText("")
|
||||
case k == tcell.KeyEsc:
|
||||
ui.isSearching = false
|
||||
// ui.searchBar.SetText("")
|
||||
|
|
Loading…
Reference in a new issue