mirror of
https://github.com/jesseduffield/lazydocker.git
synced 2026-07-25 08:31:03 +00:00
allow searching in any list view
This commit is contained in:
parent
b6b5373999
commit
702361559f
8 changed files with 52 additions and 24 deletions
|
|
@ -52,8 +52,8 @@ func (gui *Gui) getMessageHeight(wrap bool, message string, width int) int {
|
||||||
return lineCount
|
return lineCount
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) getConfirmationPanelDimensions(g *gocui.Gui, wrap bool, prompt string) (int, int, int, int) {
|
func (gui *Gui) getConfirmationPanelDimensions(wrap bool, prompt string) (int, int, int, int) {
|
||||||
width, height := g.Size()
|
width, height := gui.g.Size()
|
||||||
panelWidth := width / 2
|
panelWidth := width / 2
|
||||||
panelHeight := gui.getMessageHeight(wrap, prompt, panelWidth)
|
panelHeight := gui.getMessageHeight(wrap, prompt, panelWidth)
|
||||||
return width/2 - panelWidth/2,
|
return width/2 - panelWidth/2,
|
||||||
|
|
@ -73,7 +73,7 @@ func (gui *Gui) createPromptPanel(title string, handleConfirm func(*gocui.Gui, *
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) prepareConfirmationPanel(title, prompt string, hasLoader bool) error {
|
func (gui *Gui) prepareConfirmationPanel(title, prompt string, hasLoader bool) error {
|
||||||
x0, y0, x1, y1 := gui.getConfirmationPanelDimensions(gui.g, true, prompt)
|
x0, y0, x1, y1 := gui.getConfirmationPanelDimensions(true, prompt)
|
||||||
confirmationView := gui.Views.Confirmation
|
confirmationView := gui.Views.Confirmation
|
||||||
_, err := gui.g.SetView("confirmation", x0, y0, x1, y1, 0)
|
_, err := gui.g.SetView("confirmation", x0, y0, x1, y1, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,7 @@ type guiState struct {
|
||||||
|
|
||||||
type searchingState struct {
|
type searchingState struct {
|
||||||
view *gocui.View
|
view *gocui.View
|
||||||
|
panel ISideListPanel
|
||||||
isSearching bool
|
isSearching bool
|
||||||
searchString string
|
searchString string
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -450,13 +450,6 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
||||||
Handler: gui.handleImagesBulkCommand,
|
Handler: gui.handleImagesBulkCommand,
|
||||||
Description: gui.Tr.ViewBulkCommands,
|
Description: gui.Tr.ViewBulkCommands,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
ViewName: "images",
|
|
||||||
Key: '/',
|
|
||||||
Modifier: gocui.ModNone,
|
|
||||||
Handler: wrappedHandler(gui.handleOpenImageSearch),
|
|
||||||
Description: gui.Tr.FilterList,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
ViewName: "volumes",
|
ViewName: "volumes",
|
||||||
Key: '[',
|
Key: '[',
|
||||||
|
|
@ -620,6 +613,17 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, panel := range gui.allListPanels() {
|
||||||
|
bindings = append(bindings,
|
||||||
|
&Binding{
|
||||||
|
ViewName: panel.View().Name(),
|
||||||
|
Key: '/',
|
||||||
|
Modifier: gocui.ModNone,
|
||||||
|
Handler: wrappedHandler(gui.handleOpenSearch),
|
||||||
|
Description: gui.Tr.LcFilter,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return bindings
|
return bindings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,9 @@ type SideListPanel[T comparable] struct {
|
||||||
onClick func(T) error
|
onClick func(T) error
|
||||||
|
|
||||||
getDisplayStrings func(T) []string
|
getDisplayStrings func(T) []string
|
||||||
|
|
||||||
|
// function to be called after re-rendering list. Can be nil
|
||||||
|
onRerender func() error
|
||||||
}
|
}
|
||||||
|
|
||||||
type ISideListPanel interface {
|
type ISideListPanel interface {
|
||||||
|
|
@ -80,6 +83,7 @@ type ISideListPanel interface {
|
||||||
HandleSelect() error
|
HandleSelect() error
|
||||||
View() *gocui.View
|
View() *gocui.View
|
||||||
Refocus()
|
Refocus()
|
||||||
|
RerenderList() error
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ ISideListPanel = &SideListPanel[int]{}
|
var _ ISideListPanel = &SideListPanel[int]{}
|
||||||
|
|
@ -275,6 +279,12 @@ func (self *SideListPanel[T]) RerenderList() error {
|
||||||
}
|
}
|
||||||
fmt.Fprint(self.view, renderedTable)
|
fmt.Fprint(self.view, renderedTable)
|
||||||
|
|
||||||
|
if self.onRerender != nil {
|
||||||
|
if err := self.onRerender(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if self.view == self.gui.CurrentView() {
|
if self.view == self.gui.CurrentView() {
|
||||||
return self.HandleSelect()
|
return self.HandleSelect()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,9 @@ func (gui *Gui) getMenuPanel() *SideListPanel[*MenuItem] {
|
||||||
getDisplayStrings: func(menuItem *MenuItem) []string {
|
getDisplayStrings: func(menuItem *MenuItem) []string {
|
||||||
return menuItem.LabelColumns
|
return menuItem.LabelColumns
|
||||||
},
|
},
|
||||||
|
onRerender: func() error {
|
||||||
|
return gui.resizePopupPanel(gui.Views.Menu)
|
||||||
|
},
|
||||||
|
|
||||||
// the menu panel doesn't actually have any contexts to display on the main view
|
// the menu panel doesn't actually have any contexts to display on the main view
|
||||||
// so what follows are all dummy values
|
// so what follows are all dummy values
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,15 @@ import (
|
||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/gocui"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (gui *Gui) handleOpenImageSearch() error {
|
func (gui *Gui) handleOpenSearch() error {
|
||||||
return gui.handleOpenSearch(gui.Views.Images)
|
panel, ok := gui.currentListPanel()
|
||||||
}
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleOpenSearch(view *gocui.View) error {
|
|
||||||
gui.State.Searching.isSearching = true
|
gui.State.Searching.isSearching = true
|
||||||
gui.State.Searching.view = view
|
gui.State.Searching.view = panel.View()
|
||||||
|
gui.State.Searching.panel = panel
|
||||||
|
|
||||||
return gui.switchFocus(gui.Views.Search)
|
return gui.switchFocus(gui.Views.Search)
|
||||||
}
|
}
|
||||||
|
|
@ -18,7 +20,7 @@ func (gui *Gui) handleOpenSearch(view *gocui.View) error {
|
||||||
func (gui *Gui) onNewSearchString(value string) error {
|
func (gui *Gui) onNewSearchString(value string) error {
|
||||||
// need to refresh the right list panel.
|
// need to refresh the right list panel.
|
||||||
gui.State.Searching.searchString = value
|
gui.State.Searching.searchString = value
|
||||||
return gui.Panels.Images.RerenderList()
|
return gui.State.Searching.panel.RerenderList()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) wrapEditor(f func(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) bool) func(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) bool {
|
func (gui *Gui) wrapEditor(f func(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) bool) func(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) bool {
|
||||||
|
|
@ -44,9 +46,11 @@ func (gui *Gui) clearSearch() error {
|
||||||
gui.State.Searching.searchString = ""
|
gui.State.Searching.searchString = ""
|
||||||
gui.State.Searching.isSearching = false
|
gui.State.Searching.isSearching = false
|
||||||
gui.State.Searching.view = nil
|
gui.State.Searching.view = nil
|
||||||
|
panel := gui.State.Searching.panel
|
||||||
|
gui.State.Searching.panel = nil
|
||||||
gui.Views.Search.ClearTextArea()
|
gui.Views.Search.ClearTextArea()
|
||||||
|
|
||||||
return gui.Panels.Images.RerenderList()
|
return panel.RerenderList()
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns to the list view with the filter still applied
|
// returns to the list view with the filter still applied
|
||||||
|
|
|
||||||
|
|
@ -133,9 +133,12 @@ func (gui *Gui) returnFocus() error {
|
||||||
// Not to be called directly. Use `switchFocus` instead
|
// Not to be called directly. Use `switchFocus` instead
|
||||||
func (gui *Gui) pushView(name string) {
|
func (gui *Gui) pushView(name string) {
|
||||||
// No matter what view we're pushing, we first remove all popup panels from the stack
|
// No matter what view we're pushing, we first remove all popup panels from the stack
|
||||||
gui.State.ViewStack = lo.Filter(gui.State.ViewStack, func(viewName string, _ int) bool {
|
// (unless it's the search view because we may be searching the menu panel)
|
||||||
return !gui.isPopupPanel(viewName)
|
if name != "search" {
|
||||||
})
|
gui.State.ViewStack = lo.Filter(gui.State.ViewStack, func(viewName string, _ int) bool {
|
||||||
|
return !gui.isPopupPanel(viewName)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// If we're pushing a side panel, we remove all other panels
|
// If we're pushing a side panel, we remove all other panels
|
||||||
if lo.Contains(gui.sideViewNames(), name) {
|
if lo.Contains(gui.sideViewNames(), name) {
|
||||||
|
|
@ -318,21 +321,21 @@ func (gui *Gui) currentViewName() string {
|
||||||
func (gui *Gui) resizeCurrentPopupPanel(g *gocui.Gui) error {
|
func (gui *Gui) resizeCurrentPopupPanel(g *gocui.Gui) error {
|
||||||
v := g.CurrentView()
|
v := g.CurrentView()
|
||||||
if gui.isPopupPanel(v.Name()) {
|
if gui.isPopupPanel(v.Name()) {
|
||||||
return gui.resizePopupPanel(g, v)
|
return gui.resizePopupPanel(v)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) resizePopupPanel(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) resizePopupPanel(v *gocui.View) error {
|
||||||
// If the confirmation panel is already displayed, just resize the width,
|
// If the confirmation panel is already displayed, just resize the width,
|
||||||
// otherwise continue
|
// otherwise continue
|
||||||
content := v.Buffer()
|
content := v.Buffer()
|
||||||
x0, y0, x1, y1 := gui.getConfirmationPanelDimensions(g, v.Wrap, content)
|
x0, y0, x1, y1 := gui.getConfirmationPanelDimensions(v.Wrap, content)
|
||||||
vx0, vy0, vx1, vy1 := v.Dimensions()
|
vx0, vy0, vx1, vy1 := v.Dimensions()
|
||||||
if vx0 == x0 && vy0 == y0 && vx1 == x1 && vy1 == y1 {
|
if vx0 == x0 && vy0 == y0 && vx1 == x1 && vy1 == y1 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
_, err := g.SetView(v.Name(), x0, y0, x1, y1, 0)
|
_, err := gui.g.SetView(v.Name(), x0, y0, x1, y1, 0)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -482,6 +485,7 @@ func (gui *Gui) currentSidePanel() (ISideListPanel, bool) {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns the current list panel. If no list panel is focused, returns false.
|
||||||
func (gui *Gui) currentListPanel() (ISideListPanel, bool) {
|
func (gui *Gui) currentListPanel() (ISideListPanel, bool) {
|
||||||
viewName := gui.currentViewName()
|
viewName := gui.currentViewName()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ type TranslationSet struct {
|
||||||
Confirm string
|
Confirm string
|
||||||
Return string
|
Return string
|
||||||
FocusMain string
|
FocusMain string
|
||||||
|
LcFilter string
|
||||||
StopContainer string
|
StopContainer string
|
||||||
RestartingStatus string
|
RestartingStatus string
|
||||||
StartingStatus string
|
StartingStatus string
|
||||||
|
|
@ -148,6 +149,7 @@ func englishSet() TranslationSet {
|
||||||
|
|
||||||
Return: "return",
|
Return: "return",
|
||||||
FocusMain: "focus main panel",
|
FocusMain: "focus main panel",
|
||||||
|
LcFilter: "filter list",
|
||||||
Navigate: "navigate",
|
Navigate: "navigate",
|
||||||
Execute: "execute",
|
Execute: "execute",
|
||||||
Close: "close",
|
Close: "close",
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue