cleaning things up

pull/392/head
Jesse Duffield 2 years ago
parent 0bdd0e0539
commit b453ce8940

@ -121,7 +121,7 @@ func (gui *Gui) getContainersPanel() *SideListPanel[*commands.Container] {
func (gui *Gui) renderContainerEnv(container *commands.Container) error {
if !container.DetailsLoaded() {
return gui.T.NewTask(func(stop chan struct{}) {
_ = gui.renderStringMain(gui.Tr.WaitingForContainerInfo)
_ = gui.RenderStringMain(gui.Tr.WaitingForContainerInfo)
})
}
@ -130,7 +130,7 @@ func (gui *Gui) renderContainerEnv(container *commands.Container) error {
mainView.Wrap = gui.Config.UserConfig.Gui.WrapMainPanel
return gui.T.NewTask(func(stop chan struct{}) {
_ = gui.renderStringMain(gui.containerEnv(container))
_ = gui.RenderStringMain(gui.containerEnv(container))
})
}
@ -164,7 +164,7 @@ func (gui *Gui) containerEnv(container *commands.Container) string {
func (gui *Gui) renderContainerConfig(container *commands.Container) error {
if !container.DetailsLoaded() {
return gui.T.NewTask(func(stop chan struct{}) {
_ = gui.renderStringMain(gui.Tr.WaitingForContainerInfo)
_ = gui.RenderStringMain(gui.Tr.WaitingForContainerInfo)
})
}
@ -214,7 +214,7 @@ func (gui *Gui) renderContainerConfig(container *commands.Container) error {
output += fmt.Sprintf("\nFull details:\n\n%s", string(data))
return gui.T.NewTask(func(stop chan struct{}) {
_ = gui.renderStringMain(output)
_ = gui.RenderStringMain(output)
})
}
@ -301,12 +301,6 @@ func (gui *Gui) renderContainersAndServices() error {
return nil
}
type removeContainerOption struct {
description string
command string
configOptions types.ContainerRemoveOptions
}
func (gui *Gui) handleHideStoppedContainers(g *gocui.Gui, v *gocui.View) error {
gui.State.ShowExitedContainers = !gui.State.ShowExitedContainers

@ -8,22 +8,22 @@ import (
func TestFilteredListGet(t *testing.T) {
tests := []struct {
f FilteredList[int]
f *FilteredList[int]
args int
want int
}{
{
f: FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 1, 2}},
f: &FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 1, 2}},
args: 1,
want: 2,
},
{
f: FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 1, 2}},
f: &FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 1, 2}},
args: 2,
want: 3,
},
{
f: FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{1}},
f: &FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{1}},
args: 0,
want: 2,
},
@ -38,15 +38,15 @@ func TestFilteredListGet(t *testing.T) {
func TestFilteredListLen(t *testing.T) {
tests := []struct {
f FilteredList[int]
f *FilteredList[int]
want int
}{
{
f: FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 1, 2}},
f: &FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 1, 2}},
want: 3,
},
{
f: FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{1}},
f: &FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{1}},
want: 1,
},
}
@ -60,19 +60,19 @@ func TestFilteredListLen(t *testing.T) {
func TestFilteredListFilter(t *testing.T) {
tests := []struct {
f FilteredList[int]
f *FilteredList[int]
args func(int, int) bool
want FilteredList[int]
want *FilteredList[int]
}{
{
f: FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 1, 2}},
f: &FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 1, 2}},
args: func(i int, _ int) bool { return i%2 == 0 },
want: FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{1}},
want: &FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{1}},
},
{
f: FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 1, 2}},
f: &FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 1, 2}},
args: func(i int, _ int) bool { return i%2 == 1 },
want: FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 2}},
want: &FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 2}},
},
}
@ -84,19 +84,19 @@ func TestFilteredListFilter(t *testing.T) {
func TestFilteredListSort(t *testing.T) {
tests := []struct {
f FilteredList[int]
f *FilteredList[int]
args func(int, int) bool
want FilteredList[int]
want *FilteredList[int]
}{
{
f: FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 1, 2}},
f: &FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 1, 2}},
args: func(i int, j int) bool { return i < j },
want: FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 1, 2}},
want: &FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 1, 2}},
},
{
f: FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 1, 2}},
f: &FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 1, 2}},
args: func(i int, j int) bool { return i > j },
want: FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{2, 1, 0}},
want: &FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{2, 1, 0}},
},
}
@ -108,22 +108,22 @@ func TestFilteredListSort(t *testing.T) {
func TestFilteredListGetIndex(t *testing.T) {
tests := []struct {
f FilteredList[int]
f *FilteredList[int]
args int
want int
}{
{
f: FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 1, 2}},
f: &FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 1, 2}},
args: 1,
want: 0,
},
{
f: FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 1, 2}},
f: &FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 1, 2}},
args: 2,
want: 1,
},
{
f: FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{1}},
f: &FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{1}},
args: 0,
want: -1,
},
@ -138,15 +138,15 @@ func TestFilteredListGetIndex(t *testing.T) {
func TestFilteredListGetItems(t *testing.T) {
tests := []struct {
f FilteredList[int]
f *FilteredList[int]
want []int
}{
{
f: FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 1, 2}},
f: &FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 1, 2}},
want: []int{1, 2, 3},
},
{
f: FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{1}},
f: &FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{1}},
want: []int{2},
},
}
@ -159,19 +159,19 @@ func TestFilteredListGetItems(t *testing.T) {
func TestFilteredListSetItems(t *testing.T) {
tests := []struct {
f FilteredList[int]
f *FilteredList[int]
args []int
want FilteredList[int]
want *FilteredList[int]
}{
{
f: FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 1, 2}},
f: &FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{0, 1, 2}},
args: []int{4, 5, 6},
want: FilteredList[int]{allItems: []int{4, 5, 6}, indices: []int{0, 1, 2}},
want: &FilteredList[int]{allItems: []int{4, 5, 6}, indices: []int{0, 1, 2}},
},
{
f: FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{1}},
f: &FilteredList[int]{allItems: []int{1, 2, 3}, indices: []int{1}},
args: []int{4},
want: FilteredList[int]{allItems: []int{4}, indices: []int{0}},
want: &FilteredList[int]{allItems: []int{4}, indices: []int{0}},
},
}

@ -79,7 +79,7 @@ type guiState struct {
SubProcessOutput string
Stats map[string]commands.ContainerStats
// if true, we show containers with an 'exited' status in the contaniners panel
// if true, we show containers with an 'exited' status in the containers panel
ShowExitedContainers bool
ScreenMode WindowMaximisation
@ -138,7 +138,7 @@ func NewGui(log *logrus.Entry, dockerCommand *commands.DockerCommand, oSCommand
}
deadlock.Opts.Disable = !gui.Config.Debug
deadlock.Opts.DeadlockTimeout = 5 * time.Second
deadlock.Opts.DeadlockTimeout = 10 * time.Second
return gui, nil
}
@ -257,7 +257,8 @@ func (gui *Gui) Run() error {
gui.goEvery(time.Millisecond*30, gui.reRenderMain)
gui.goEvery(time.Millisecond*1000, gui.updateContainerDetails)
gui.goEvery(time.Millisecond*1000, gui.checkForContextChange)
gui.goEvery(time.Millisecond*1000, gui.rerenderContainersAndServices)
// we need to regularly re-render these because their stats will be changed in the background
gui.goEvery(time.Millisecond*1000, gui.renderContainersAndServices)
}()
err = g.MainLoop()
@ -271,12 +272,6 @@ func (gui *Gui) updateContainerDetails() error {
return gui.DockerCommand.UpdateContainerDetails(gui.Panels.Containers.list.GetAllItems())
}
func (gui *Gui) rerenderContainersAndServices() error {
// we need to regularly re-render these because their stats will be changed in the background
gui.renderContainersAndServices()
return nil
}
func (gui *Gui) refresh() {
go func() {
if err := gui.refreshProject(); err != nil {
@ -426,7 +421,7 @@ func (gui *Gui) handleCustomCommand(g *gocui.Gui, v *gocui.View) error {
})
}
func (gui *Gui) shouldRefresh(key string) bool {
func (gui *Gui) ShouldRefresh(key string) bool {
if gui.State.Panels.Main.ObjectKey == key {
return false
}
@ -435,10 +430,6 @@ func (gui *Gui) shouldRefresh(key string) bool {
return true
}
func (gui *Gui) ShouldRefresh(key string) bool {
return gui.shouldRefresh(key)
}
func (gui *Gui) initiallyFocusedViewName() string {
if gui.DockerCommand.InDockerComposeProject {
return "services"

@ -60,7 +60,11 @@ func (gui *Gui) getImagesPanel() *SideListPanel[*commands.Image] {
return a.ID < b.ID
},
getDisplayStrings: func(image *commands.Image) []string {
return []string{image.Name, image.Tag, utils.FormatDecimalBytes(int(image.Image.Size))}
return []string{
image.Name,
image.Tag,
utils.FormatDecimalBytes(int(image.Image.Size)),
}
},
}
}
@ -86,7 +90,7 @@ func (gui *Gui) renderImageConfig(image *commands.Image) error {
mainView.Autoscroll = false
mainView.Wrap = false // don't care what your config is this page is ugly without wrapping
_ = gui.renderStringMain(output)
_ = gui.RenderStringMain(output)
})
}

@ -101,7 +101,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
return view, err
}
for _, viewName := range gui.controlledBoundsViewNames() {
for _, viewName := range gui.autoPositionedViewNames() {
_, err := setViewFromDimensions(viewName, viewName)
if err != nil && err.Error() != UNKNOWN_VIEW_ERROR_MSG {
return err

@ -108,7 +108,7 @@ func (gui *Gui) renderCredits(_project *commands.Project) error {
configBuf.String(),
}, "\n\n")
_ = gui.renderStringMain(dashboardString)
_ = gui.RenderStringMain(dashboardString)
})
}
@ -151,7 +151,7 @@ func (gui *Gui) renderDockerComposeConfig(_project *commands.Project) error {
mainView.Wrap = gui.Config.UserConfig.Gui.WrapMainPanel
config := gui.DockerCommand.DockerComposeConfig()
_ = gui.renderStringMain(config)
_ = gui.RenderStringMain(config)
})
}

@ -98,7 +98,7 @@ func (gui *Gui) getServicesPanel() *SideListPanel[*commands.Service] {
func (gui *Gui) renderServiceContainerConfig(service *commands.Service) error {
if service.Container == nil {
return gui.renderStringMain(gui.Tr.NoContainer)
return gui.RenderStringMain(gui.Tr.NoContainer)
}
return gui.renderContainerConfig(service.Container)
@ -106,7 +106,7 @@ func (gui *Gui) renderServiceContainerConfig(service *commands.Service) error {
func (gui *Gui) renderServiceContainerEnv(service *commands.Service) error {
if service.Container == nil {
return gui.renderStringMain(gui.Tr.NoContainer)
return gui.RenderStringMain(gui.Tr.NoContainer)
}
return gui.renderContainerEnv(service.Container)

@ -106,13 +106,8 @@ func (gui *Gui) focusPoint(selectedX int, selectedY int, lineCount int, v *gocui
}
}
func (gui *Gui) focusY(selectedY int, lineCount int, v *gocui.View) {
gui.focusPoint(0, selectedY, lineCount, v)
}
// TODO: combine with above
func (gui *Gui) FocusY(selectedY int, lineCount int, v *gocui.View) {
gui.focusY(selectedY, lineCount, v)
gui.focusPoint(0, selectedY, lineCount, v)
}
func (gui *Gui) ResetOrigin(v *gocui.View) {
@ -149,13 +144,8 @@ func (gui *Gui) renderString(g *gocui.Gui, viewName, s string) error {
return nil
}
func (gui *Gui) renderStringMain(s string) error {
return gui.renderString(gui.g, "main", s)
}
// TODO: merge with above
func (gui *Gui) RenderStringMain(s string) error {
return gui.renderStringMain(s)
return gui.renderString(gui.g, "main", s)
}
// reRenderString sets the main view's content, without changing its origin
@ -225,22 +215,6 @@ func (gui *Gui) resizePopupPanel(v *gocui.View) error {
return err
}
func (gui *Gui) changeSelectedLine(line *int, total int, up bool) {
if up {
if *line == -1 || *line == 0 {
return
}
*line -= 1
} else {
if *line == -1 || *line == total-1 {
return
}
*line += 1
}
}
func (gui *Gui) renderPanelOptions() error {
currentView := gui.g.CurrentView()
switch currentView.Name() {
@ -260,11 +234,6 @@ func (gui *Gui) popupPanelFocused() bool {
return gui.isPopupPanel(gui.currentViewName())
}
// TODO: merge into above
func (gui *Gui) PopupPanelFocused() bool {
return gui.popupPanelFocused()
}
func (gui *Gui) clearMainView() {
mainView := gui.Views.Main
mainView.Clear()
@ -272,7 +241,14 @@ func (gui *Gui) clearMainView() {
_ = mainView.SetCursor(0, 0)
}
func (gui *Gui) handleClick(v *gocui.View, itemCount int, selectedLine *int, handleSelect func(*gocui.Gui, *gocui.View) error) error {
func (gui *Gui) HandleClick(v *gocui.View, itemCount int, selectedLine *int, handleSelect func() error) error {
wrappedHandleSelect := func(g *gocui.Gui, v *gocui.View) error {
return handleSelect()
}
return gui.handleClickAux(v, itemCount, selectedLine, wrappedHandleSelect)
}
func (gui *Gui) handleClickAux(v *gocui.View, itemCount int, selectedLine *int, handleSelect func(*gocui.Gui, *gocui.View) error) error {
if gui.popupPanelFocused() && v != nil && !gui.isPopupPanel(v.Name()) {
return nil
}
@ -301,14 +277,6 @@ func (gui *Gui) handleClick(v *gocui.View, itemCount int, selectedLine *int, han
return handleSelect(gui.g, v)
}
// TODO: combine with above
func (gui *Gui) HandleClick(v *gocui.View, itemCount int, selectedLine *int, handleSelect func() error) error {
wrappedHandleSelect := func(g *gocui.Gui, v *gocui.View) error {
return handleSelect()
}
return gui.handleClick(v, itemCount, selectedLine, wrappedHandleSelect)
}
func (gui *Gui) nextScreenMode() error {
if gui.currentViewName() == "main" {
gui.State.ScreenMode = prevIntInCycle([]WindowMaximisation{SCREEN_NORMAL, SCREEN_HALF, SCREEN_FULL}, gui.State.ScreenMode)

@ -3,6 +3,7 @@ package gui
import (
"github.com/fatih/color"
"github.com/jesseduffield/gocui"
"github.com/samber/lo"
)
type Views struct {
@ -20,7 +21,7 @@ type Views struct {
Options *gocui.View
Information *gocui.View
AppStatus *gocui.View
// text that prompts you to enter text in the Search view
// text that prompts you to enter text in the Filter view
FilterPrefix *gocui.View
// appears next to the SearchPrefix view, it's where you type in the search string
Filter *gocui.View
@ -36,33 +37,36 @@ type Views struct {
type viewNameMapping struct {
viewPtr **gocui.View
name string
// if true, we handle the position/size of the view in arrangement.go. Otherwise
// we handle it manually.
autoPosition bool
}
func (gui *Gui) orderedViewNameMappings() []viewNameMapping {
return []viewNameMapping{
// first layer. Ordering within this layer does not matter because there are
// no overlapping views
{viewPtr: &gui.Views.Project, name: "project"},
{viewPtr: &gui.Views.Services, name: "services"},
{viewPtr: &gui.Views.Containers, name: "containers"},
{viewPtr: &gui.Views.Images, name: "images"},
{viewPtr: &gui.Views.Volumes, name: "volumes"},
{viewPtr: &gui.Views.Project, name: "project", autoPosition: true},
{viewPtr: &gui.Views.Services, name: "services", autoPosition: true},
{viewPtr: &gui.Views.Containers, name: "containers", autoPosition: true},
{viewPtr: &gui.Views.Images, name: "images", autoPosition: true},
{viewPtr: &gui.Views.Volumes, name: "volumes", autoPosition: true},
{viewPtr: &gui.Views.Main, name: "main"},
{viewPtr: &gui.Views.Main, name: "main", autoPosition: true},
// bottom line
{viewPtr: &gui.Views.Options, name: "options"},
{viewPtr: &gui.Views.AppStatus, name: "appStatus"},
{viewPtr: &gui.Views.Information, name: "information"},
{viewPtr: &gui.Views.Filter, name: "filter"},
{viewPtr: &gui.Views.FilterPrefix, name: "filterPrefix"},
{viewPtr: &gui.Views.Options, name: "options", autoPosition: true},
{viewPtr: &gui.Views.AppStatus, name: "appStatus", autoPosition: true},
{viewPtr: &gui.Views.Information, name: "information", autoPosition: true},
{viewPtr: &gui.Views.Filter, name: "filter", autoPosition: true},
{viewPtr: &gui.Views.FilterPrefix, name: "filterPrefix", autoPosition: true},
// popups.
{viewPtr: &gui.Views.Menu, name: "menu"},
{viewPtr: &gui.Views.Confirmation, name: "confirmation"},
{viewPtr: &gui.Views.Menu, name: "menu", autoPosition: false},
{viewPtr: &gui.Views.Confirmation, name: "confirmation", autoPosition: false},
// this guy will cover everything else when it appears
{viewPtr: &gui.Views.Limit, name: "limit"},
{viewPtr: &gui.Views.Limit, name: "limit", autoPosition: true},
}
}
@ -155,19 +159,12 @@ func (gui *Gui) popupViewNames() []string {
}
// these views have their position and size determined by arrangement.go
func (gui *Gui) controlledBoundsViewNames() []string {
return []string{
"project",
"services",
"containers",
"images",
"volumes",
"options",
"information",
"appStatus",
"main",
"limit",
"filterPrefix",
"filter",
}
func (gui *Gui) autoPositionedViewNames() []string {
views := lo.Filter(gui.orderedViewNameMappings(), func(viewNameMapping viewNameMapping, _ int) bool {
return viewNameMapping.autoPosition
})
return lo.Map(views, func(viewNameMapping viewNameMapping, _ int) string {
return viewNameMapping.name
})
}

@ -81,7 +81,7 @@ func (gui *Gui) renderVolumeConfig(volume *commands.Volume) error {
output += utils.WithPadding("Size: ", padding) + utils.FormatBinaryBytes(int(volume.Volume.UsageData.Size)) + "\n"
}
_ = gui.renderStringMain(output)
_ = gui.RenderStringMain(output)
})
}

Loading…
Cancel
Save