mirror of
https://github.com/jesseduffield/lazydocker.git
synced 2026-07-25 08:31:03 +00:00
Merge pull request #272 from lpessoa/lp-order-by-status
This commit is contained in:
commit
9fad29449c
4 changed files with 241 additions and 40 deletions
|
|
@ -258,6 +258,7 @@ func (c *DockerCommand) RefreshContainersAndServices() error {
|
||||||
c.Containers = containers
|
c.Containers = containers
|
||||||
c.Services = services
|
c.Services = services
|
||||||
c.DisplayContainers = c.filterOutExited(displayContainers)
|
c.DisplayContainers = c.filterOutExited(displayContainers)
|
||||||
|
c.DisplayContainers = c.sortedContainers(c.DisplayContainers)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -289,6 +290,27 @@ func (c *DockerCommand) filterOutExited(containers []*Container) []*Container {
|
||||||
return toReturn
|
return toReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
func (c *DockerCommand) sortedContainers(containers []*Container) []*Container {
|
||||||
|
if !c.Config.UserConfig.Gui.LegacySortContainers {
|
||||||
|
states := map[string]int{
|
||||||
|
"running": 1,
|
||||||
|
"exited": 2,
|
||||||
|
"created": 3,
|
||||||
|
}
|
||||||
|
sort.Slice(containers, func(i, j int) bool {
|
||||||
|
stateLeft := states[containers[i].Container.State]
|
||||||
|
stateRight := states[containers[j].Container.State]
|
||||||
|
if stateLeft == stateRight {
|
||||||
|
return containers[i].Name < containers[j].Name
|
||||||
|
}
|
||||||
|
return states[containers[i].Container.State] < states[containers[j].Container.State]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return containers
|
||||||
|
}
|
||||||
|
|
||||||
// obtainStandaloneContainers returns standalone containers. Standalone containers are containers which are either one-off containers, or whose service is not part of this docker-compose context
|
// obtainStandaloneContainers returns standalone containers. Standalone containers are containers which are either one-off containers, or whose service is not part of this docker-compose context
|
||||||
func (c *DockerCommand) obtainStandaloneContainers(containers []*Container, services []*Service) []*Container {
|
func (c *DockerCommand) obtainStandaloneContainers(containers []*Container, services []*Service) []*Container {
|
||||||
standaloneContainers := []*Container{}
|
standaloneContainers := []*Container{}
|
||||||
|
|
|
||||||
171
pkg/commands/sort_container_test.go
Normal file
171
pkg/commands/sort_container_test.go
Normal file
|
|
@ -0,0 +1,171 @@
|
||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/jesseduffield/lazydocker/pkg/config"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func sampleContainers(userConfig *config.AppConfig) []*Container {
|
||||||
|
return []*Container{
|
||||||
|
{
|
||||||
|
ID: "1",
|
||||||
|
Name: "1",
|
||||||
|
Container: types.Container{
|
||||||
|
State: "exited",
|
||||||
|
},
|
||||||
|
Config: userConfig,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "2",
|
||||||
|
Name: "2",
|
||||||
|
Container: types.Container{
|
||||||
|
State: "running",
|
||||||
|
},
|
||||||
|
Config: userConfig,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "3",
|
||||||
|
Name: "3",
|
||||||
|
Container: types.Container{
|
||||||
|
State: "running",
|
||||||
|
},
|
||||||
|
Config: userConfig,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "4",
|
||||||
|
Name: "4",
|
||||||
|
Container: types.Container{
|
||||||
|
State: "created",
|
||||||
|
},
|
||||||
|
Config: userConfig,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func expectedPerStatusContainers(appConfig *config.AppConfig) []*Container {
|
||||||
|
return []*Container{
|
||||||
|
{
|
||||||
|
ID: "2",
|
||||||
|
Name: "2",
|
||||||
|
Container: types.Container{
|
||||||
|
State: "running",
|
||||||
|
},
|
||||||
|
Config: appConfig,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "3",
|
||||||
|
Name: "3",
|
||||||
|
Container: types.Container{
|
||||||
|
State: "running",
|
||||||
|
},
|
||||||
|
Config: appConfig,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "1",
|
||||||
|
Name: "1",
|
||||||
|
Container: types.Container{
|
||||||
|
State: "exited",
|
||||||
|
},
|
||||||
|
Config: appConfig,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "4",
|
||||||
|
Name: "4",
|
||||||
|
Container: types.Container{
|
||||||
|
State: "created",
|
||||||
|
},
|
||||||
|
Config: appConfig,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func expectedLegacySortedContainers(appConfig *config.AppConfig) []*Container {
|
||||||
|
return []*Container{
|
||||||
|
{
|
||||||
|
ID: "1",
|
||||||
|
Name: "1",
|
||||||
|
Container: types.Container{
|
||||||
|
State: "exited",
|
||||||
|
},
|
||||||
|
Config: appConfig,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "2",
|
||||||
|
Name: "2",
|
||||||
|
Container: types.Container{
|
||||||
|
State: "running",
|
||||||
|
},
|
||||||
|
Config: appConfig,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "3",
|
||||||
|
Name: "3",
|
||||||
|
Container: types.Container{
|
||||||
|
State: "running",
|
||||||
|
},
|
||||||
|
Config: appConfig,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "4",
|
||||||
|
Name: "4",
|
||||||
|
Container: types.Container{
|
||||||
|
State: "created",
|
||||||
|
},
|
||||||
|
Config: appConfig,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertEqualContainers(t *testing.T, left *Container, right *Container) {
|
||||||
|
assert.Equal(t, left.Container.State, right.Container.State)
|
||||||
|
assert.Equal(t, left.Container.ID, right.Container.ID)
|
||||||
|
assert.Equal(t, left.Name, right.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSortContainers(t *testing.T) {
|
||||||
|
appConfig := NewDummyAppConfig()
|
||||||
|
appConfig.UserConfig = &config.UserConfig{
|
||||||
|
Gui: config.GuiConfig{
|
||||||
|
LegacySortContainers: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
command := &DockerCommand{
|
||||||
|
Config: appConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
containers := sampleContainers(appConfig)
|
||||||
|
|
||||||
|
sorted := expectedPerStatusContainers(appConfig)
|
||||||
|
|
||||||
|
ct := command.sortedContainers(containers)
|
||||||
|
|
||||||
|
assert.Equal(t, len(ct), len(sorted))
|
||||||
|
|
||||||
|
for i := 0; i < len(ct); i++ {
|
||||||
|
assertEqualContainers(t, sorted[i], ct[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLegacySortedContainers(t *testing.T) {
|
||||||
|
appConfig := NewDummyAppConfig()
|
||||||
|
appConfig.UserConfig = &config.UserConfig{
|
||||||
|
Gui: config.GuiConfig{
|
||||||
|
LegacySortContainers: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
command := &DockerCommand{
|
||||||
|
Config: appConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
containers := sampleContainers(appConfig)
|
||||||
|
|
||||||
|
sorted := expectedLegacySortedContainers(appConfig)
|
||||||
|
|
||||||
|
ct := command.sortedContainers(containers)
|
||||||
|
|
||||||
|
for i := 0; i < len(ct); i++ {
|
||||||
|
assertEqualContainers(t, sorted[i], ct[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -20,7 +20,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/OpenPeeDeeP/xdg"
|
"github.com/OpenPeeDeeP/xdg"
|
||||||
yaml "github.com/jesseduffield/yaml"
|
"github.com/jesseduffield/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UserConfig holds all of the user-configurable options
|
// UserConfig holds all of the user-configurable options
|
||||||
|
|
@ -106,6 +106,11 @@ type GuiConfig struct {
|
||||||
|
|
||||||
// WrapMainPanel determines whether we use word wrap on the main panel
|
// WrapMainPanel determines whether we use word wrap on the main panel
|
||||||
WrapMainPanel bool `yaml:"wrapMainPanel,omitempty"`
|
WrapMainPanel bool `yaml:"wrapMainPanel,omitempty"`
|
||||||
|
|
||||||
|
// LegacySortContainers determines if containers should be sorted using legacy approach.
|
||||||
|
// By default, containers are now sorted by status. This setting allows users to
|
||||||
|
// use legacy behaviour instead.
|
||||||
|
LegacySortContainers bool `yaml:"legacySortContainers,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommandTemplatesConfig determines what commands actually get called when we
|
// CommandTemplatesConfig determines what commands actually get called when we
|
||||||
|
|
@ -319,6 +324,7 @@ func GetDefaultConfig() UserConfig {
|
||||||
ShowAllContainers: false,
|
ShowAllContainers: false,
|
||||||
ReturnImmediately: false,
|
ReturnImmediately: false,
|
||||||
WrapMainPanel: false,
|
WrapMainPanel: false,
|
||||||
|
LegacySortContainers: false,
|
||||||
},
|
},
|
||||||
ConfirmOnQuit: false,
|
ConfirmOnQuit: false,
|
||||||
CommandTemplates: CommandTemplatesConfig{
|
CommandTemplates: CommandTemplatesConfig{
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@ type TranslationSet struct {
|
||||||
RunCustomCommand string
|
RunCustomCommand string
|
||||||
ViewBulkCommands string
|
ViewBulkCommands string
|
||||||
OpenInBrowser string
|
OpenInBrowser string
|
||||||
|
SortContainersByState string
|
||||||
|
|
||||||
LogsTitle string
|
LogsTitle string
|
||||||
ConfigTitle string
|
ConfigTitle string
|
||||||
|
|
@ -152,6 +153,7 @@ func englishSet() TranslationSet {
|
||||||
RunCustomCommand: "run predefined custom command",
|
RunCustomCommand: "run predefined custom command",
|
||||||
ViewBulkCommands: "view bulk commands",
|
ViewBulkCommands: "view bulk commands",
|
||||||
OpenInBrowser: "open in browser (first port is http)",
|
OpenInBrowser: "open in browser (first port is http)",
|
||||||
|
SortContainersByState: "sort containers by state",
|
||||||
|
|
||||||
GlobalTitle: "Global",
|
GlobalTitle: "Global",
|
||||||
MainTitle: "Main",
|
MainTitle: "Main",
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue