mirror of
https://github.com/jesseduffield/lazydocker.git
synced 2026-07-23 23:51:03 +00:00
more refactoring of list panels
This commit is contained in:
parent
5d498c796a
commit
fc592b5806
18 changed files with 239 additions and 221 deletions
|
|
@ -2,6 +2,7 @@ package gui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/jesseduffield/lazycore/pkg/boxlayout"
|
"github.com/jesseduffield/lazycore/pkg/boxlayout"
|
||||||
|
"github.com/jesseduffield/lazydocker/pkg/gui/panels"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/utils"
|
"github.com/jesseduffield/lazydocker/pkg/utils"
|
||||||
"github.com/mattn/go-runewidth"
|
"github.com/mattn/go-runewidth"
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
|
|
@ -129,12 +130,12 @@ func (gui *Gui) infoSectionChildren(informationStr string, appStatus string) []*
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) sideViewNames() []string {
|
func (gui *Gui) sideViewNames() []string {
|
||||||
visibleSidePanels := lo.Filter(gui.allSidePanels(), func(panel ISideListPanel, _ int) bool {
|
visibleSidePanels := lo.Filter(gui.allSidePanels(), func(panel panels.ISideListPanel, _ int) bool {
|
||||||
return !panel.IsHidden()
|
return !panel.IsHidden()
|
||||||
})
|
})
|
||||||
|
|
||||||
return lo.Map(visibleSidePanels, func(panel ISideListPanel, _ int) string {
|
return lo.Map(visibleSidePanels, func(panel panels.ISideListPanel, _ int) string {
|
||||||
return panel.View().Name()
|
return panel.GetView().Name()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,12 @@ import (
|
||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/gocui"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/commands"
|
"github.com/jesseduffield/lazydocker/pkg/commands"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/config"
|
"github.com/jesseduffield/lazydocker/pkg/config"
|
||||||
|
"github.com/jesseduffield/lazydocker/pkg/gui/panels"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/utils"
|
"github.com/jesseduffield/lazydocker/pkg/utils"
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (gui *Gui) getContainersPanel() *SideListPanel[*commands.Container] {
|
func (gui *Gui) getContainersPanel() *panels.SideListPanel[*commands.Container] {
|
||||||
// Standalone containers are containers which are either one-off containers, or whose service is not part of this docker-compose context.
|
// Standalone containers are containers which are either one-off containers, or whose service is not part of this docker-compose context.
|
||||||
isStandaloneContainer := func(container *commands.Container) bool {
|
isStandaloneContainer := func(container *commands.Container) bool {
|
||||||
if container.OneOff || container.ServiceName == "" {
|
if container.OneOff || container.ServiceName == "" {
|
||||||
|
|
@ -27,34 +28,34 @@ func (gui *Gui) getContainersPanel() *SideListPanel[*commands.Container] {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return &SideListPanel[*commands.Container]{
|
return &panels.SideListPanel[*commands.Container]{
|
||||||
ContextState: &ContextState[*commands.Container]{
|
ContextState: &panels.ContextState[*commands.Container]{
|
||||||
GetContexts: func() []ContextConfig[*commands.Container] {
|
GetContexts: func() []panels.ContextConfig[*commands.Container] {
|
||||||
return []ContextConfig[*commands.Container]{
|
return []panels.ContextConfig[*commands.Container]{
|
||||||
{
|
{
|
||||||
key: "logs",
|
Key: "logs",
|
||||||
title: gui.Tr.LogsTitle,
|
Title: gui.Tr.LogsTitle,
|
||||||
render: gui.renderContainerLogsToMain,
|
Render: gui.renderContainerLogsToMain,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "stats",
|
Key: "stats",
|
||||||
title: gui.Tr.StatsTitle,
|
Title: gui.Tr.StatsTitle,
|
||||||
render: gui.renderContainerStats,
|
Render: gui.renderContainerStats,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "env",
|
Key: "env",
|
||||||
title: gui.Tr.EnvTitle,
|
Title: gui.Tr.EnvTitle,
|
||||||
render: gui.renderContainerEnv,
|
Render: gui.renderContainerEnv,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "config",
|
Key: "config",
|
||||||
title: gui.Tr.ConfigTitle,
|
Title: gui.Tr.ConfigTitle,
|
||||||
render: gui.renderContainerConfig,
|
Render: gui.renderContainerConfig,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "top",
|
Key: "top",
|
||||||
title: gui.Tr.TopTitle,
|
Title: gui.Tr.TopTitle,
|
||||||
render: gui.renderContainerTop,
|
Render: gui.renderContainerTop,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -62,12 +63,12 @@ func (gui *Gui) getContainersPanel() *SideListPanel[*commands.Container] {
|
||||||
return "containers-" + container.ID + "-" + container.Container.State
|
return "containers-" + container.ID + "-" + container.Container.State
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ListPanel: ListPanel[*commands.Container]{
|
ListPanel: panels.ListPanel[*commands.Container]{
|
||||||
List: NewFilteredList[*commands.Container](),
|
List: panels.NewFilteredList[*commands.Container](),
|
||||||
view: gui.Views.Containers,
|
View: gui.Views.Containers,
|
||||||
},
|
},
|
||||||
NoItemsMessage: gui.Tr.NoContainers,
|
NoItemsMessage: gui.Tr.NoContainers,
|
||||||
gui: gui.intoInterface(),
|
Gui: gui.intoInterface(),
|
||||||
// sortedContainers returns containers sorted by state if c.SortContainersByState is true (follows 1- running, 2- exited, 3- created)
|
// sortedContainers returns containers sorted by state if c.SortContainersByState is true (follows 1- running, 2- exited, 3- created)
|
||||||
// and sorted by name if c.SortContainersByState is false
|
// and sorted by name if c.SortContainersByState is false
|
||||||
Sort: func(a *commands.Container, b *commands.Container) bool {
|
Sort: func(a *commands.Container, b *commands.Container) bool {
|
||||||
|
|
@ -282,7 +283,7 @@ func (gui *Gui) refreshContainersAndServices() error {
|
||||||
if i == originalSelectedLineIdx {
|
if i == originalSelectedLineIdx {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
gui.Panels.Services.setSelectedLineIdx(i)
|
gui.Panels.Services.SetSelectedLineIdx(i)
|
||||||
gui.Panels.Services.Refocus()
|
gui.Panels.Services.Refocus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ func (gui *Gui) handleOpenFilter() error {
|
||||||
|
|
||||||
func (gui *Gui) onNewFilterNeedle(value string) error {
|
func (gui *Gui) onNewFilterNeedle(value string) error {
|
||||||
gui.State.Filter.needle = value
|
gui.State.Filter.needle = value
|
||||||
gui.ResetOrigin(gui.State.Filter.panel.View())
|
gui.ResetOrigin(gui.State.Filter.panel.GetView())
|
||||||
return gui.State.Filter.panel.RerenderList()
|
return gui.State.Filter.panel.RerenderList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -59,7 +59,7 @@ func (gui *Gui) clearFilter() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
gui.ResetOrigin(panel.View())
|
gui.ResetOrigin(panel.GetView())
|
||||||
|
|
||||||
return panel.RerenderList()
|
return panel.RerenderList()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ func (gui *Gui) switchFocusAux(newView *gocui.View) error {
|
||||||
|
|
||||||
newViewStack := gui.State.ViewStack
|
newViewStack := gui.State.ViewStack
|
||||||
|
|
||||||
if gui.State.Filter.panel != nil && !lo.Contains(newViewStack, gui.State.Filter.panel.View().Name()) {
|
if gui.State.Filter.panel != nil && !lo.Contains(newViewStack, gui.State.Filter.panel.GetView().Name()) {
|
||||||
if err := gui.clearFilter(); err != nil {
|
if err := gui.clearFilter(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import (
|
||||||
lcUtils "github.com/jesseduffield/lazycore/pkg/utils"
|
lcUtils "github.com/jesseduffield/lazycore/pkg/utils"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/commands"
|
"github.com/jesseduffield/lazydocker/pkg/commands"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/config"
|
"github.com/jesseduffield/lazydocker/pkg/config"
|
||||||
|
"github.com/jesseduffield/lazydocker/pkg/gui/panels"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/i18n"
|
"github.com/jesseduffield/lazydocker/pkg/i18n"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/tasks"
|
"github.com/jesseduffield/lazydocker/pkg/tasks"
|
||||||
"github.com/sasha-s/go-deadlock"
|
"github.com/sasha-s/go-deadlock"
|
||||||
|
|
@ -49,12 +50,12 @@ type Gui struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Panels struct {
|
type Panels struct {
|
||||||
Projects *SideListPanel[*commands.Project]
|
Projects *panels.SideListPanel[*commands.Project]
|
||||||
Services *SideListPanel[*commands.Service]
|
Services *panels.SideListPanel[*commands.Service]
|
||||||
Containers *SideListPanel[*commands.Container]
|
Containers *panels.SideListPanel[*commands.Container]
|
||||||
Images *SideListPanel[*commands.Image]
|
Images *panels.SideListPanel[*commands.Image]
|
||||||
Volumes *SideListPanel[*commands.Volume]
|
Volumes *panels.SideListPanel[*commands.Volume]
|
||||||
Menu *SideListPanel[*MenuItem]
|
Menu *panels.SideListPanel[*MenuItem]
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutexes struct {
|
type Mutexes struct {
|
||||||
|
|
@ -94,7 +95,7 @@ type filterState struct {
|
||||||
// or we've committed the filter and we're back in the list view
|
// or we've committed the filter and we're back in the list view
|
||||||
active bool
|
active bool
|
||||||
// The panel that we're filtering.
|
// The panel that we're filtering.
|
||||||
panel ISideListPanel
|
panel panels.ISideListPanel
|
||||||
// The string that we're filtering on
|
// The string that we're filtering on
|
||||||
needle string
|
needle string
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,21 +10,22 @@ import (
|
||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/gocui"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/commands"
|
"github.com/jesseduffield/lazydocker/pkg/commands"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/config"
|
"github.com/jesseduffield/lazydocker/pkg/config"
|
||||||
|
"github.com/jesseduffield/lazydocker/pkg/gui/panels"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/utils"
|
"github.com/jesseduffield/lazydocker/pkg/utils"
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (gui *Gui) getImagesPanel() *SideListPanel[*commands.Image] {
|
func (gui *Gui) getImagesPanel() *panels.SideListPanel[*commands.Image] {
|
||||||
noneLabel := "<none>"
|
noneLabel := "<none>"
|
||||||
|
|
||||||
return &SideListPanel[*commands.Image]{
|
return &panels.SideListPanel[*commands.Image]{
|
||||||
ContextState: &ContextState[*commands.Image]{
|
ContextState: &panels.ContextState[*commands.Image]{
|
||||||
GetContexts: func() []ContextConfig[*commands.Image] {
|
GetContexts: func() []panels.ContextConfig[*commands.Image] {
|
||||||
return []ContextConfig[*commands.Image]{
|
return []panels.ContextConfig[*commands.Image]{
|
||||||
{
|
{
|
||||||
key: "config",
|
Key: "config",
|
||||||
title: gui.Tr.ConfigTitle,
|
Title: gui.Tr.ConfigTitle,
|
||||||
render: func(image *commands.Image) error {
|
Render: func(image *commands.Image) error {
|
||||||
return gui.renderImageConfig(image)
|
return gui.renderImageConfig(image)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -34,12 +35,12 @@ func (gui *Gui) getImagesPanel() *SideListPanel[*commands.Image] {
|
||||||
return "images-" + image.ID
|
return "images-" + image.ID
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ListPanel: ListPanel[*commands.Image]{
|
ListPanel: panels.ListPanel[*commands.Image]{
|
||||||
List: NewFilteredList[*commands.Image](),
|
List: panels.NewFilteredList[*commands.Image](),
|
||||||
view: gui.Views.Images,
|
View: gui.Views.Images,
|
||||||
},
|
},
|
||||||
NoItemsMessage: gui.Tr.NoImages,
|
NoItemsMessage: gui.Tr.NoImages,
|
||||||
gui: gui.intoInterface(),
|
Gui: gui.intoInterface(),
|
||||||
Sort: func(a *commands.Image, b *commands.Image) bool {
|
Sort: func(a *commands.Image, b *commands.Image) bool {
|
||||||
if a.Name == noneLabel && b.Name != noneLabel {
|
if a.Name == noneLabel && b.Name != noneLabel {
|
||||||
return false
|
return false
|
||||||
|
|
@ -114,7 +115,7 @@ func (gui *Gui) refreshStateImages() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) FilterString(view *gocui.View) string {
|
func (gui *Gui) FilterString(view *gocui.View) string {
|
||||||
if gui.State.Filter.panel != nil && gui.State.Filter.panel.View() != view {
|
if gui.State.Filter.panel != nil && gui.State.Filter.panel.GetView() != view {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -492,12 +492,12 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
||||||
|
|
||||||
for _, panel := range gui.allSidePanels() {
|
for _, panel := range gui.allSidePanels() {
|
||||||
bindings = append(bindings, []*Binding{
|
bindings = append(bindings, []*Binding{
|
||||||
{ViewName: panel.View().Name(), Key: gocui.KeyArrowLeft, Modifier: gocui.ModNone, Handler: gui.previousView},
|
{ViewName: panel.GetView().Name(), Key: gocui.KeyArrowLeft, Modifier: gocui.ModNone, Handler: gui.previousView},
|
||||||
{ViewName: panel.View().Name(), Key: gocui.KeyArrowRight, Modifier: gocui.ModNone, Handler: gui.nextView},
|
{ViewName: panel.GetView().Name(), Key: gocui.KeyArrowRight, Modifier: gocui.ModNone, Handler: gui.nextView},
|
||||||
{ViewName: panel.View().Name(), Key: 'h', Modifier: gocui.ModNone, Handler: gui.previousView},
|
{ViewName: panel.GetView().Name(), Key: 'h', Modifier: gocui.ModNone, Handler: gui.previousView},
|
||||||
{ViewName: panel.View().Name(), Key: 'l', Modifier: gocui.ModNone, Handler: gui.nextView},
|
{ViewName: panel.GetView().Name(), Key: 'l', Modifier: gocui.ModNone, Handler: gui.nextView},
|
||||||
{ViewName: panel.View().Name(), Key: gocui.KeyTab, Modifier: gocui.ModNone, Handler: gui.nextView},
|
{ViewName: panel.GetView().Name(), Key: gocui.KeyTab, Modifier: gocui.ModNone, Handler: gui.nextView},
|
||||||
{ViewName: panel.View().Name(), Key: gocui.KeyBacktab, Modifier: gocui.ModNone, Handler: gui.previousView},
|
{ViewName: panel.GetView().Name(), Key: gocui.KeyBacktab, Modifier: gocui.ModNone, Handler: gui.previousView},
|
||||||
}...)
|
}...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -514,7 +514,7 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, panel := range gui.allListPanels() {
|
for _, panel := range gui.allListPanels() {
|
||||||
setUpDownClickBindings(panel.View().Name(), panel.HandlePrevLine, panel.HandleNextLine, panel.HandleClick)
|
setUpDownClickBindings(panel.GetView().Name(), panel.HandlePrevLine, panel.HandleNextLine, panel.HandleClick)
|
||||||
}
|
}
|
||||||
|
|
||||||
setUpDownClickBindings("main", gui.scrollUpMain, gui.scrollDownMain, gui.handleMainClick)
|
setUpDownClickBindings("main", gui.scrollUpMain, gui.scrollDownMain, gui.handleMainClick)
|
||||||
|
|
@ -522,21 +522,21 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
||||||
for _, panel := range gui.allSidePanels() {
|
for _, panel := range gui.allSidePanels() {
|
||||||
bindings = append(bindings,
|
bindings = append(bindings,
|
||||||
&Binding{
|
&Binding{
|
||||||
ViewName: panel.View().Name(),
|
ViewName: panel.GetView().Name(),
|
||||||
Key: gocui.KeyEnter,
|
Key: gocui.KeyEnter,
|
||||||
Modifier: gocui.ModNone,
|
Modifier: gocui.ModNone,
|
||||||
Handler: gui.handleEnterMain,
|
Handler: gui.handleEnterMain,
|
||||||
Description: gui.Tr.FocusMain,
|
Description: gui.Tr.FocusMain,
|
||||||
},
|
},
|
||||||
&Binding{
|
&Binding{
|
||||||
ViewName: panel.View().Name(),
|
ViewName: panel.GetView().Name(),
|
||||||
Key: '[',
|
Key: '[',
|
||||||
Modifier: gocui.ModNone,
|
Modifier: gocui.ModNone,
|
||||||
Handler: wrappedHandler(panel.HandlePrevContext),
|
Handler: wrappedHandler(panel.HandlePrevContext),
|
||||||
Description: gui.Tr.PreviousContext,
|
Description: gui.Tr.PreviousContext,
|
||||||
},
|
},
|
||||||
&Binding{
|
&Binding{
|
||||||
ViewName: panel.View().Name(),
|
ViewName: panel.GetView().Name(),
|
||||||
Key: ']',
|
Key: ']',
|
||||||
Modifier: gocui.ModNone,
|
Modifier: gocui.ModNone,
|
||||||
Handler: wrappedHandler(panel.HandleNextContext),
|
Handler: wrappedHandler(panel.HandleNextContext),
|
||||||
|
|
@ -547,7 +547,7 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
||||||
|
|
||||||
for _, panel := range gui.allListPanels() {
|
for _, panel := range gui.allListPanels() {
|
||||||
bindings = append(bindings, &Binding{
|
bindings = append(bindings, &Binding{
|
||||||
ViewName: panel.View().Name(),
|
ViewName: panel.GetView().Name(),
|
||||||
Key: '/',
|
Key: '/',
|
||||||
Modifier: gocui.ModNone,
|
Modifier: gocui.ModNone,
|
||||||
Handler: wrappedHandler(gui.handleOpenFilter),
|
Handler: wrappedHandler(gui.handleOpenFilter),
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package gui
|
package gui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/jesseduffield/lazydocker/pkg/gui/panels"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/utils"
|
"github.com/jesseduffield/lazydocker/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -22,14 +23,14 @@ type CreateMenuOptions struct {
|
||||||
HideCancel bool
|
HideCancel bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) getMenuPanel() *SideListPanel[*MenuItem] {
|
func (gui *Gui) getMenuPanel() *panels.SideListPanel[*MenuItem] {
|
||||||
return &SideListPanel[*MenuItem]{
|
return &panels.SideListPanel[*MenuItem]{
|
||||||
ListPanel: ListPanel[*MenuItem]{
|
ListPanel: panels.ListPanel[*MenuItem]{
|
||||||
List: NewFilteredList[*MenuItem](),
|
List: panels.NewFilteredList[*MenuItem](),
|
||||||
view: gui.Views.Menu,
|
View: gui.Views.Menu,
|
||||||
},
|
},
|
||||||
NoItemsMessage: "",
|
NoItemsMessage: "",
|
||||||
gui: gui.intoInterface(),
|
Gui: gui.intoInterface(),
|
||||||
OnClick: gui.onMenuPress,
|
OnClick: gui.onMenuPress,
|
||||||
Sort: nil,
|
Sort: nil,
|
||||||
GetDisplayStrings: func(menuItem *MenuItem) []string {
|
GetDisplayStrings: func(menuItem *MenuItem) []string {
|
||||||
|
|
@ -101,7 +102,7 @@ func (gui *Gui) Menu(opts CreateMenuOptions) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
gui.Panels.Menu.SetItems(opts.Items)
|
gui.Panels.Menu.SetItems(opts.Items)
|
||||||
gui.Panels.Menu.setSelectedLineIdx(0)
|
gui.Panels.Menu.SetSelectedLineIdx(0)
|
||||||
|
|
||||||
if err := gui.Panels.Menu.RerenderList(); err != nil {
|
if err := gui.Panels.Menu.RerenderList(); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
7
pkg/gui/panels.go
Normal file
7
pkg/gui/panels.go
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
package gui
|
||||||
|
|
||||||
|
import "github.com/jesseduffield/lazydocker/pkg/gui/panels"
|
||||||
|
|
||||||
|
func (gui *Gui) intoInterface() panels.IGui {
|
||||||
|
return gui
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package gui
|
package panels
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sort"
|
"sort"
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package gui
|
package panels
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
42
pkg/gui/panels/list_panel.go
Normal file
42
pkg/gui/panels/list_panel.go
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
package panels
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jesseduffield/gocui"
|
||||||
|
lcUtils "github.com/jesseduffield/lazycore/pkg/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListPanel[T comparable] struct {
|
||||||
|
SelectedIdx int
|
||||||
|
List *FilteredList[T]
|
||||||
|
View *gocui.View
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ListPanel[T]) SetSelectedLineIdx(value int) {
|
||||||
|
clampedValue := 0
|
||||||
|
if self.List.Len() > 0 {
|
||||||
|
clampedValue = lcUtils.Clamp(value, 0, self.List.Len()-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.SelectedIdx = clampedValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ListPanel[T]) clampSelectedLineIdx() {
|
||||||
|
clamped := lcUtils.Clamp(self.SelectedIdx, 0, self.List.Len()-1)
|
||||||
|
|
||||||
|
if clamped != self.SelectedIdx {
|
||||||
|
self.SelectedIdx = clamped
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// moves the cursor up or down by the given amount (up for negative values)
|
||||||
|
func (self *ListPanel[T]) moveSelectedLine(delta int) {
|
||||||
|
self.SetSelectedLineIdx(self.SelectedIdx + delta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ListPanel[T]) SelectNextLine() {
|
||||||
|
self.moveSelectedLine(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ListPanel[T]) SelectPrevLine() {
|
||||||
|
self.moveSelectedLine(-1)
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package gui
|
package panels
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
@ -6,53 +6,23 @@ import (
|
||||||
|
|
||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/gocui"
|
||||||
lcUtils "github.com/jesseduffield/lazycore/pkg/utils"
|
|
||||||
"github.com/jesseduffield/lazydocker/pkg/utils"
|
"github.com/jesseduffield/lazydocker/pkg/utils"
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ListPanel[T comparable] struct {
|
type ISideListPanel interface {
|
||||||
SelectedIdx int
|
SetContextIndex(int)
|
||||||
List *FilteredList[T]
|
HandleSelect() error
|
||||||
view *gocui.View
|
GetView() *gocui.View
|
||||||
}
|
Refocus()
|
||||||
|
RerenderList() error
|
||||||
func (self *ListPanel[T]) setSelectedLineIdx(value int) {
|
IsFilterDisabled() bool
|
||||||
clampedValue := 0
|
IsHidden() bool
|
||||||
if self.List.Len() > 0 {
|
HandleNextLine() error
|
||||||
clampedValue = lcUtils.Clamp(value, 0, self.List.Len()-1)
|
HandlePrevLine() error
|
||||||
}
|
HandleClick() error
|
||||||
|
HandlePrevContext() error
|
||||||
self.SelectedIdx = clampedValue
|
HandleNextContext() error
|
||||||
}
|
|
||||||
|
|
||||||
func (self *ListPanel[T]) clampSelectedLineIdx() {
|
|
||||||
clamped := lcUtils.Clamp(self.SelectedIdx, 0, self.List.Len()-1)
|
|
||||||
|
|
||||||
if clamped != self.SelectedIdx {
|
|
||||||
self.SelectedIdx = clamped
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// moves the cursor up or down by the given amount (up for negative values)
|
|
||||||
func (self *ListPanel[T]) moveSelectedLine(delta int) {
|
|
||||||
self.setSelectedLineIdx(self.SelectedIdx + delta)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *ListPanel[T]) SelectNextLine() {
|
|
||||||
self.moveSelectedLine(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *ListPanel[T]) SelectPrevLine() {
|
|
||||||
self.moveSelectedLine(-1)
|
|
||||||
}
|
|
||||||
|
|
||||||
type ContextState[T any] struct {
|
|
||||||
contextIdx int
|
|
||||||
// contexts []ContextConfig[T]
|
|
||||||
GetContexts func() []ContextConfig[T]
|
|
||||||
// this tells us whether we need to re-render to the main panel
|
|
||||||
GetContextCacheKey func(item T) string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// list panel at the side of the screen that renders content to the main panel
|
// list panel at the side of the screen that renders content to the main panel
|
||||||
|
|
@ -65,7 +35,7 @@ type SideListPanel[T comparable] struct {
|
||||||
// and it has focus. Leave empty if you don't want to render anything
|
// and it has focus. Leave empty if you don't want to render anything
|
||||||
NoItemsMessage string
|
NoItemsMessage string
|
||||||
|
|
||||||
gui IGui
|
Gui IGui
|
||||||
|
|
||||||
// this Filter is applied on top of additional default filters
|
// this Filter is applied on top of additional default filters
|
||||||
Filter func(T) bool
|
Filter func(T) bool
|
||||||
|
|
@ -85,27 +55,20 @@ type SideListPanel[T comparable] struct {
|
||||||
Hide func() bool
|
Hide func() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type ISideListPanel interface {
|
|
||||||
SetContextIndex(int)
|
|
||||||
HandleSelect() error
|
|
||||||
View() *gocui.View
|
|
||||||
Refocus()
|
|
||||||
RerenderList() error
|
|
||||||
IsFilterDisabled() bool
|
|
||||||
IsHidden() bool
|
|
||||||
HandleNextLine() error
|
|
||||||
HandlePrevLine() error
|
|
||||||
HandleClick() error
|
|
||||||
HandlePrevContext() error
|
|
||||||
HandleNextContext() error
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ ISideListPanel = &SideListPanel[int]{}
|
var _ ISideListPanel = &SideListPanel[int]{}
|
||||||
|
|
||||||
|
type ContextState[T any] struct {
|
||||||
|
contextIdx int
|
||||||
|
// contexts []ContextConfig[T]
|
||||||
|
GetContexts func() []ContextConfig[T]
|
||||||
|
// this tells us whether we need to re-render to the main panel
|
||||||
|
GetContextCacheKey func(item T) string
|
||||||
|
}
|
||||||
|
|
||||||
type ContextConfig[T any] struct {
|
type ContextConfig[T any] struct {
|
||||||
key string
|
Key string
|
||||||
title string
|
Title string
|
||||||
render func(item T) error
|
Render func(item T) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type IGui interface {
|
type IGui interface {
|
||||||
|
|
@ -121,16 +84,12 @@ type IGui interface {
|
||||||
Update(func() error)
|
Update(func() error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) intoInterface() IGui {
|
|
||||||
return gui
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *SideListPanel[T]) HandleClick() error {
|
func (self *SideListPanel[T]) HandleClick() error {
|
||||||
itemCount := self.List.Len()
|
itemCount := self.List.Len()
|
||||||
handleSelect := self.HandleSelect
|
handleSelect := self.HandleSelect
|
||||||
selectedLine := &self.SelectedIdx
|
selectedLine := &self.SelectedIdx
|
||||||
|
|
||||||
if err := self.gui.HandleClick(self.view, itemCount, selectedLine, handleSelect); err != nil {
|
if err := self.Gui.HandleClick(self.View, itemCount, selectedLine, handleSelect); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -144,8 +103,8 @@ func (self *SideListPanel[T]) HandleClick() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SideListPanel[T]) View() *gocui.View {
|
func (self *SideListPanel[T]) GetView() *gocui.View {
|
||||||
return self.view
|
return self.View
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SideListPanel[T]) HandleSelect() error {
|
func (self *SideListPanel[T]) HandleSelect() error {
|
||||||
|
|
@ -156,7 +115,7 @@ func (self *SideListPanel[T]) HandleSelect() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.NoItemsMessage != "" {
|
if self.NoItemsMessage != "" {
|
||||||
return self.gui.RenderStringMain(self.NoItemsMessage)
|
return self.Gui.RenderStringMain(self.NoItemsMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -173,25 +132,25 @@ func (self *SideListPanel[T]) renderContext(item T) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
key := self.ContextState.GetCurrentContextKey(item)
|
key := self.ContextState.GetCurrentContextKey(item)
|
||||||
if !self.gui.ShouldRefresh(key) {
|
if !self.Gui.ShouldRefresh(key) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
mainView := self.gui.GetMainView()
|
mainView := self.Gui.GetMainView()
|
||||||
mainView.Tabs = self.ContextState.GetContextTitles()
|
mainView.Tabs = self.ContextState.GetContextTitles()
|
||||||
mainView.TabIndex = self.ContextState.contextIdx
|
mainView.TabIndex = self.ContextState.contextIdx
|
||||||
|
|
||||||
return self.ContextState.GetCurrentContext().render(item)
|
return self.ContextState.GetCurrentContext().Render(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *ContextState[T]) GetContextTitles() []string {
|
func (self *ContextState[T]) GetContextTitles() []string {
|
||||||
return lo.Map(self.GetContexts(), func(context ContextConfig[T], _ int) string {
|
return lo.Map(self.GetContexts(), func(context ContextConfig[T], _ int) string {
|
||||||
return context.title
|
return context.Title
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *ContextState[T]) GetCurrentContextKey(item T) string {
|
func (self *ContextState[T]) GetCurrentContextKey(item T) string {
|
||||||
return self.GetContextCacheKey(item) + "-" + self.GetCurrentContext().key
|
return self.GetContextCacheKey(item) + "-" + self.GetCurrentContext().Key
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *ContextState[T]) GetCurrentContext() ContextConfig[T] {
|
func (self *ContextState[T]) GetCurrentContext() ContextConfig[T] {
|
||||||
|
|
@ -263,7 +222,7 @@ func (self *SideListPanel[T]) HandlePrevContext() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SideListPanel[T]) Refocus() {
|
func (self *SideListPanel[T]) Refocus() {
|
||||||
self.gui.FocusY(self.SelectedIdx, self.List.Len(), self.view)
|
self.Gui.FocusY(self.SelectedIdx, self.List.Len(), self.View)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SideListPanel[T]) SetItems(items []T) {
|
func (self *SideListPanel[T]) SetItems(items []T) {
|
||||||
|
|
@ -272,14 +231,14 @@ func (self *SideListPanel[T]) SetItems(items []T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SideListPanel[T]) FilterAndSort() {
|
func (self *SideListPanel[T]) FilterAndSort() {
|
||||||
filterString := self.gui.FilterString(self.view)
|
filterString := self.Gui.FilterString(self.View)
|
||||||
|
|
||||||
self.List.Filter(func(item T, index int) bool {
|
self.List.Filter(func(item T, index int) bool {
|
||||||
if self.Filter != nil && !self.Filter(item) {
|
if self.Filter != nil && !self.Filter(item) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if lo.SomeBy(self.gui.IgnoreStrings(), func(ignore string) bool {
|
if lo.SomeBy(self.Gui.IgnoreStrings(), func(ignore string) bool {
|
||||||
return lo.SomeBy(self.GetDisplayStrings(item), func(searchString string) bool {
|
return lo.SomeBy(self.GetDisplayStrings(item), func(searchString string) bool {
|
||||||
return strings.Contains(searchString, ignore)
|
return strings.Contains(searchString, ignore)
|
||||||
})
|
})
|
||||||
|
|
@ -304,8 +263,8 @@ func (self *SideListPanel[T]) FilterAndSort() {
|
||||||
func (self *SideListPanel[T]) RerenderList() error {
|
func (self *SideListPanel[T]) RerenderList() error {
|
||||||
self.FilterAndSort()
|
self.FilterAndSort()
|
||||||
|
|
||||||
self.gui.Update(func() error {
|
self.Gui.Update(func() error {
|
||||||
self.view.Clear()
|
self.View.Clear()
|
||||||
table := lo.Map(self.List.GetItems(), func(item T, index int) []string {
|
table := lo.Map(self.List.GetItems(), func(item T, index int) []string {
|
||||||
return self.GetDisplayStrings(item)
|
return self.GetDisplayStrings(item)
|
||||||
})
|
})
|
||||||
|
|
@ -313,7 +272,7 @@ func (self *SideListPanel[T]) RerenderList() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Fprint(self.view, renderedTable)
|
fmt.Fprint(self.View, renderedTable)
|
||||||
|
|
||||||
if self.OnRerender != nil {
|
if self.OnRerender != nil {
|
||||||
if err := self.OnRerender(); err != nil {
|
if err := self.OnRerender(); err != nil {
|
||||||
|
|
@ -321,7 +280,7 @@ func (self *SideListPanel[T]) RerenderList() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.view == self.gui.CurrentView() {
|
if self.View == self.Gui.CurrentView() {
|
||||||
return self.HandleSelect()
|
return self.HandleSelect()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/gocui"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/commands"
|
"github.com/jesseduffield/lazydocker/pkg/commands"
|
||||||
|
"github.com/jesseduffield/lazydocker/pkg/gui/panels"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/utils"
|
"github.com/jesseduffield/lazydocker/pkg/utils"
|
||||||
"github.com/jesseduffield/yaml"
|
"github.com/jesseduffield/yaml"
|
||||||
)
|
)
|
||||||
|
|
@ -15,35 +16,35 @@ import (
|
||||||
// Although at the moment we'll only have one project, in future we could have
|
// Although at the moment we'll only have one project, in future we could have
|
||||||
// a list of projects in the project panel.
|
// a list of projects in the project panel.
|
||||||
|
|
||||||
func (gui *Gui) getProjectPanel() *SideListPanel[*commands.Project] {
|
func (gui *Gui) getProjectPanel() *panels.SideListPanel[*commands.Project] {
|
||||||
return &SideListPanel[*commands.Project]{
|
return &panels.SideListPanel[*commands.Project]{
|
||||||
ContextState: &ContextState[*commands.Project]{
|
ContextState: &panels.ContextState[*commands.Project]{
|
||||||
GetContexts: func() []ContextConfig[*commands.Project] {
|
GetContexts: func() []panels.ContextConfig[*commands.Project] {
|
||||||
if gui.DockerCommand.InDockerComposeProject {
|
if gui.DockerCommand.InDockerComposeProject {
|
||||||
return []ContextConfig[*commands.Project]{
|
return []panels.ContextConfig[*commands.Project]{
|
||||||
{
|
{
|
||||||
key: "logs",
|
Key: "logs",
|
||||||
title: gui.Tr.LogsTitle,
|
Title: gui.Tr.LogsTitle,
|
||||||
render: gui.renderAllLogs,
|
Render: gui.renderAllLogs,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "config",
|
Key: "config",
|
||||||
title: gui.Tr.DockerComposeConfigTitle,
|
Title: gui.Tr.DockerComposeConfigTitle,
|
||||||
render: gui.renderDockerComposeConfig,
|
Render: gui.renderDockerComposeConfig,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "credits",
|
Key: "credits",
|
||||||
title: gui.Tr.CreditsTitle,
|
Title: gui.Tr.CreditsTitle,
|
||||||
render: gui.renderCredits,
|
Render: gui.renderCredits,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return []ContextConfig[*commands.Project]{
|
return []panels.ContextConfig[*commands.Project]{
|
||||||
{
|
{
|
||||||
key: "credits",
|
Key: "credits",
|
||||||
title: gui.Tr.CreditsTitle,
|
Title: gui.Tr.CreditsTitle,
|
||||||
render: gui.renderCredits,
|
Render: gui.renderCredits,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -52,12 +53,12 @@ func (gui *Gui) getProjectPanel() *SideListPanel[*commands.Project] {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
ListPanel: ListPanel[*commands.Project]{
|
ListPanel: panels.ListPanel[*commands.Project]{
|
||||||
List: NewFilteredList[*commands.Project](),
|
List: panels.NewFilteredList[*commands.Project](),
|
||||||
view: gui.Views.Project,
|
View: gui.Views.Project,
|
||||||
},
|
},
|
||||||
NoItemsMessage: "",
|
NoItemsMessage: "",
|
||||||
gui: gui.intoInterface(),
|
Gui: gui.intoInterface(),
|
||||||
|
|
||||||
Sort: func(a *commands.Project, b *commands.Project) bool {
|
Sort: func(a *commands.Project, b *commands.Project) bool {
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
|
|
@ -8,39 +8,40 @@ import (
|
||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/gocui"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/commands"
|
"github.com/jesseduffield/lazydocker/pkg/commands"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/config"
|
"github.com/jesseduffield/lazydocker/pkg/config"
|
||||||
|
"github.com/jesseduffield/lazydocker/pkg/gui/panels"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/utils"
|
"github.com/jesseduffield/lazydocker/pkg/utils"
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (gui *Gui) getServicesPanel() *SideListPanel[*commands.Service] {
|
func (gui *Gui) getServicesPanel() *panels.SideListPanel[*commands.Service] {
|
||||||
return &SideListPanel[*commands.Service]{
|
return &panels.SideListPanel[*commands.Service]{
|
||||||
ContextState: &ContextState[*commands.Service]{
|
ContextState: &panels.ContextState[*commands.Service]{
|
||||||
GetContexts: func() []ContextConfig[*commands.Service] {
|
GetContexts: func() []panels.ContextConfig[*commands.Service] {
|
||||||
return []ContextConfig[*commands.Service]{
|
return []panels.ContextConfig[*commands.Service]{
|
||||||
{
|
{
|
||||||
key: "logs",
|
Key: "logs",
|
||||||
title: gui.Tr.LogsTitle,
|
Title: gui.Tr.LogsTitle,
|
||||||
render: gui.renderServiceLogs,
|
Render: gui.renderServiceLogs,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "stats",
|
Key: "stats",
|
||||||
title: gui.Tr.StatsTitle,
|
Title: gui.Tr.StatsTitle,
|
||||||
render: gui.renderServiceStats,
|
Render: gui.renderServiceStats,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "container-env",
|
Key: "container-env",
|
||||||
title: gui.Tr.ContainerEnvTitle,
|
Title: gui.Tr.ContainerEnvTitle,
|
||||||
render: gui.renderServiceContainerEnv,
|
Render: gui.renderServiceContainerEnv,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "container-config",
|
Key: "container-config",
|
||||||
title: gui.Tr.ContainerConfigTitle,
|
Title: gui.Tr.ContainerConfigTitle,
|
||||||
render: gui.renderServiceContainerConfig,
|
Render: gui.renderServiceContainerConfig,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "top",
|
Key: "top",
|
||||||
title: gui.Tr.TopTitle,
|
Title: gui.Tr.TopTitle,
|
||||||
render: gui.renderServiceTop,
|
Render: gui.renderServiceTop,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -51,13 +52,12 @@ func (gui *Gui) getServicesPanel() *SideListPanel[*commands.Service] {
|
||||||
return "services-" + service.ID + "-" + service.Container.ID + "-" + service.Container.Container.State
|
return "services-" + service.ID + "-" + service.Container.ID + "-" + service.Container.Container.State
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ListPanel: ListPanel[*commands.Service]{
|
ListPanel: panels.ListPanel[*commands.Service]{
|
||||||
List: NewFilteredList[*commands.Service](),
|
List: panels.NewFilteredList[*commands.Service](),
|
||||||
view: gui.Views.Services,
|
View: gui.Views.Services,
|
||||||
},
|
},
|
||||||
// TODO: i18n
|
NoItemsMessage: gui.Tr.NoServices,
|
||||||
NoItemsMessage: "no service selected",
|
Gui: gui.intoInterface(),
|
||||||
gui: gui.intoInterface(),
|
|
||||||
// sort services first by whether they have a linked container, and second by alphabetical order
|
// sort services first by whether they have a linked container, and second by alphabetical order
|
||||||
Sort: func(a *commands.Service, b *commands.Service) bool {
|
Sort: func(a *commands.Service, b *commands.Service) bool {
|
||||||
if a.Container != nil && b.Container == nil {
|
if a.Container != nil && b.Container == nil {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/gocui"
|
||||||
|
"github.com/jesseduffield/lazydocker/pkg/gui/panels"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/utils"
|
"github.com/jesseduffield/lazydocker/pkg/utils"
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
"github.com/spkg/bom"
|
"github.com/spkg/bom"
|
||||||
|
|
@ -329,11 +330,11 @@ func (gui *Gui) CurrentView() *gocui.View {
|
||||||
return gui.g.CurrentView()
|
return gui.g.CurrentView()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) currentSidePanel() (ISideListPanel, bool) {
|
func (gui *Gui) currentSidePanel() (panels.ISideListPanel, bool) {
|
||||||
viewName := gui.currentViewName()
|
viewName := gui.currentViewName()
|
||||||
|
|
||||||
for _, sidePanel := range gui.allSidePanels() {
|
for _, sidePanel := range gui.allSidePanels() {
|
||||||
if sidePanel.View().Name() == viewName {
|
if sidePanel.GetView().Name() == viewName {
|
||||||
return sidePanel, true
|
return sidePanel, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -342,11 +343,11 @@ func (gui *Gui) currentSidePanel() (ISideListPanel, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns the current list panel. If no list panel is focused, returns false.
|
// returns the current list panel. If no list panel is focused, returns false.
|
||||||
func (gui *Gui) currentListPanel() (ISideListPanel, bool) {
|
func (gui *Gui) currentListPanel() (panels.ISideListPanel, bool) {
|
||||||
viewName := gui.currentViewName()
|
viewName := gui.currentViewName()
|
||||||
|
|
||||||
for _, sidePanel := range gui.allListPanels() {
|
for _, sidePanel := range gui.allListPanels() {
|
||||||
if sidePanel.View().Name() == viewName {
|
if sidePanel.GetView().Name() == viewName {
|
||||||
return sidePanel, true
|
return sidePanel, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -354,8 +355,8 @@ func (gui *Gui) currentListPanel() (ISideListPanel, bool) {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) allSidePanels() []ISideListPanel {
|
func (gui *Gui) allSidePanels() []panels.ISideListPanel {
|
||||||
return []ISideListPanel{
|
return []panels.ISideListPanel{
|
||||||
gui.Panels.Projects,
|
gui.Panels.Projects,
|
||||||
gui.Panels.Services,
|
gui.Panels.Services,
|
||||||
gui.Panels.Containers,
|
gui.Panels.Containers,
|
||||||
|
|
@ -364,6 +365,6 @@ func (gui *Gui) allSidePanels() []ISideListPanel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) allListPanels() []ISideListPanel {
|
func (gui *Gui) allListPanels() []panels.ISideListPanel {
|
||||||
return append(gui.allSidePanels(), gui.Panels.Menu)
|
return append(gui.allSidePanels(), gui.Panels.Menu)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,19 +7,20 @@ import (
|
||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/gocui"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/commands"
|
"github.com/jesseduffield/lazydocker/pkg/commands"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/config"
|
"github.com/jesseduffield/lazydocker/pkg/config"
|
||||||
|
"github.com/jesseduffield/lazydocker/pkg/gui/panels"
|
||||||
"github.com/jesseduffield/lazydocker/pkg/utils"
|
"github.com/jesseduffield/lazydocker/pkg/utils"
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (gui *Gui) getVolumesPanel() *SideListPanel[*commands.Volume] {
|
func (gui *Gui) getVolumesPanel() *panels.SideListPanel[*commands.Volume] {
|
||||||
return &SideListPanel[*commands.Volume]{
|
return &panels.SideListPanel[*commands.Volume]{
|
||||||
ContextState: &ContextState[*commands.Volume]{
|
ContextState: &panels.ContextState[*commands.Volume]{
|
||||||
GetContexts: func() []ContextConfig[*commands.Volume] {
|
GetContexts: func() []panels.ContextConfig[*commands.Volume] {
|
||||||
return []ContextConfig[*commands.Volume]{
|
return []panels.ContextConfig[*commands.Volume]{
|
||||||
{
|
{
|
||||||
key: "config",
|
Key: "config",
|
||||||
title: gui.Tr.ConfigTitle,
|
Title: gui.Tr.ConfigTitle,
|
||||||
render: gui.renderVolumeConfig,
|
Render: gui.renderVolumeConfig,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -27,12 +28,12 @@ func (gui *Gui) getVolumesPanel() *SideListPanel[*commands.Volume] {
|
||||||
return "volumes-" + volume.Name
|
return "volumes-" + volume.Name
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ListPanel: ListPanel[*commands.Volume]{
|
ListPanel: panels.ListPanel[*commands.Volume]{
|
||||||
List: NewFilteredList[*commands.Volume](),
|
List: panels.NewFilteredList[*commands.Volume](),
|
||||||
view: gui.Views.Volumes,
|
View: gui.Views.Volumes,
|
||||||
},
|
},
|
||||||
NoItemsMessage: gui.Tr.NoVolumes,
|
NoItemsMessage: gui.Tr.NoVolumes,
|
||||||
gui: gui.intoInterface(),
|
Gui: gui.intoInterface(),
|
||||||
// we're sorting these volumes based on whether they have labels defined,
|
// we're sorting these volumes based on whether they have labels defined,
|
||||||
// because those are the ones you typically care about.
|
// because those are the ones you typically care about.
|
||||||
// Within that, we also sort them alphabetically
|
// Within that, we also sort them alphabetically
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@ type TranslationSet struct {
|
||||||
NoContainer string
|
NoContainer string
|
||||||
NoImages string
|
NoImages string
|
||||||
NoVolumes string
|
NoVolumes string
|
||||||
|
NoServices string
|
||||||
RemoveImage string
|
RemoveImage string
|
||||||
RemoveVolume string
|
RemoveVolume string
|
||||||
RemoveWithoutPrune string
|
RemoveWithoutPrune string
|
||||||
|
|
@ -225,6 +226,7 @@ func englishSet() TranslationSet {
|
||||||
NoContainer: "No container",
|
NoContainer: "No container",
|
||||||
NoImages: "No images",
|
NoImages: "No images",
|
||||||
NoVolumes: "No volumes",
|
NoVolumes: "No volumes",
|
||||||
|
NoServices: "No services",
|
||||||
|
|
||||||
ConfirmQuit: "Are you sure you want to quit?",
|
ConfirmQuit: "Are you sure you want to quit?",
|
||||||
ConfirmUpProject: "Are you sure you want to 'up' your docker compose project?",
|
ConfirmUpProject: "Are you sure you want to 'up' your docker compose project?",
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue