mirror of
https://github.com/jesseduffield/lazydocker.git
synced 2026-07-21 23:01:03 +00:00
allow config option to only show standalone containers
This commit is contained in:
parent
61a10f5cc7
commit
a27b429807
6 changed files with 110 additions and 99 deletions
|
|
@ -33,7 +33,9 @@ type DockerCommand struct {
|
|||
ServiceMutex sync.Mutex
|
||||
Services []*Service
|
||||
Containers []*Container
|
||||
Images []*Image
|
||||
// DisplayContainers is the array of containers we will display in the containers panel. If Gui.ShowAllContainers is false, this will only be those containers which aren't based on a service. This reduces clutter and duplication in the UI
|
||||
DisplayContainers []*Container
|
||||
Images []*Image
|
||||
}
|
||||
|
||||
// NewDockerCommand it runs git commands
|
||||
|
|
@ -166,19 +168,13 @@ func (c *DockerCommand) GetContainersAndServices() error {
|
|||
}
|
||||
}
|
||||
|
||||
// find out which services have corresponding containers and assign them
|
||||
for _, service := range services {
|
||||
foundMatch := false
|
||||
for _, container := range containers {
|
||||
if container.ServiceID != "" && container.ServiceID == service.ID {
|
||||
foundMatch = true
|
||||
service.Container = container
|
||||
break
|
||||
}
|
||||
}
|
||||
if !foundMatch {
|
||||
service.Container = nil
|
||||
}
|
||||
c.assignContainersToServices(containers, services)
|
||||
|
||||
var displayContainers []*Container
|
||||
if c.Config.UserConfig.Gui.ShowAllContainers {
|
||||
displayContainers = containers
|
||||
} else {
|
||||
displayContainers = c.obtainStandaloneContainers(containers, services)
|
||||
}
|
||||
|
||||
// sort services first by whether they have a linked container, and second by alphabetical order
|
||||
|
|
@ -196,10 +192,39 @@ func (c *DockerCommand) GetContainersAndServices() error {
|
|||
|
||||
c.Containers = containers
|
||||
c.Services = services
|
||||
c.DisplayContainers = displayContainers
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *DockerCommand) assignContainersToServices(containers []*Container, services []*Service) {
|
||||
L:
|
||||
for _, service := range services {
|
||||
for _, container := range containers {
|
||||
if container.ServiceID != "" && container.ServiceID == service.ID {
|
||||
service.Container = container
|
||||
continue L
|
||||
}
|
||||
}
|
||||
service.Container = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *DockerCommand) obtainStandaloneContainers(containers []*Container, services []*Service) []*Container {
|
||||
standaloneContainers := []*Container{}
|
||||
L:
|
||||
for _, container := range containers {
|
||||
for _, service := range services {
|
||||
if container.ServiceID != "" && container.ServiceID == service.ID {
|
||||
continue L
|
||||
}
|
||||
}
|
||||
standaloneContainers = append(standaloneContainers, container)
|
||||
}
|
||||
|
||||
return standaloneContainers
|
||||
}
|
||||
|
||||
// GetContainers gets the docker containers
|
||||
func (c *DockerCommand) GetContainers() ([]*Container, error) {
|
||||
c.ContainerMutex.Lock()
|
||||
|
|
|
|||
|
|
@ -94,10 +94,11 @@ type ThemeConfig struct {
|
|||
}
|
||||
|
||||
type GuiConfig struct {
|
||||
ScrollHeight int `yaml:"scrollHeight,omitempty"`
|
||||
ScrollPastBottom bool `yaml:"scrollPastBottom,omitempty"`
|
||||
MouseEvents bool `yaml:"mouseEvents,omitempty"`
|
||||
Theme ThemeConfig `yaml:"theme,omitempty"`
|
||||
ScrollHeight int `yaml:"scrollHeight,omitempty"`
|
||||
ScrollPastBottom bool `yaml:"scrollPastBottom,omitempty"`
|
||||
MouseEvents bool `yaml:"mouseEvents,omitempty"`
|
||||
Theme ThemeConfig `yaml:"theme,omitempty"`
|
||||
ShowAllContainers bool `yaml:"showAllContainers,omitempty"`
|
||||
}
|
||||
|
||||
type CommandTemplatesConfig struct {
|
||||
|
|
@ -139,6 +140,7 @@ type StatsConfig struct {
|
|||
}
|
||||
|
||||
// GetDefaultConfig returns the application default configuration
|
||||
// NOTE: do not default a boolean to true, because false is the boolean zero value and this will be ignored when parsing the user's config
|
||||
func GetDefaultConfig() UserConfig {
|
||||
return UserConfig{
|
||||
Gui: GuiConfig{
|
||||
|
|
@ -150,6 +152,7 @@ func GetDefaultConfig() UserConfig {
|
|||
InactiveBorderColor: []string{"white"},
|
||||
OptionsTextColor: []string{"blue"},
|
||||
},
|
||||
ShowAllContainers: false,
|
||||
},
|
||||
Reporting: "undetermined",
|
||||
ConfirmOnQuit: false,
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ func (gui *Gui) getSelectedContainer(g *gocui.Gui) (*commands.Container, error)
|
|||
return &commands.Container{}, gui.Errors.ErrNoContainers
|
||||
}
|
||||
|
||||
return gui.DockerCommand.Containers[selectedLine], nil
|
||||
return gui.DockerCommand.DisplayContainers[selectedLine], nil
|
||||
}
|
||||
|
||||
func (gui *Gui) handleContainersFocus(g *gocui.Gui, v *gocui.View) error {
|
||||
|
|
@ -42,7 +42,7 @@ func (gui *Gui) handleContainersFocus(g *gocui.Gui, v *gocui.View) error {
|
|||
prevSelectedLine := gui.State.Panels.Containers.SelectedLine
|
||||
newSelectedLine := cy - oy
|
||||
|
||||
if newSelectedLine > len(gui.DockerCommand.Containers)-1 || len(utils.Decolorise(gui.DockerCommand.Containers[newSelectedLine].Name)) < cx {
|
||||
if newSelectedLine > len(gui.DockerCommand.DisplayContainers)-1 || len(utils.Decolorise(gui.DockerCommand.DisplayContainers[newSelectedLine].Name)) < cx {
|
||||
return gui.handleContainerSelect(gui.g, v)
|
||||
}
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ func (gui *Gui) handleContainerSelect(g *gocui.Gui, v *gocui.View) error {
|
|||
gui.State.Panels.Main.ObjectKey = key
|
||||
}
|
||||
|
||||
if err := gui.focusPoint(0, gui.State.Panels.Containers.SelectedLine, len(gui.DockerCommand.Containers), v); err != nil {
|
||||
if err := gui.focusPoint(0, gui.State.Panels.Containers.SelectedLine, len(gui.DockerCommand.DisplayContainers), v); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -147,15 +147,45 @@ func (gui *Gui) renderContainerLogs(mainView *gocui.View, container *commands.Co
|
|||
}
|
||||
|
||||
func (gui *Gui) renderLogsForRegularContainer(container *commands.Container) error {
|
||||
mainView := gui.getMainView()
|
||||
go gui.T.NewTickerTask(time.Millisecond*200, nil, func(stop, notifyStopped chan struct{}) {
|
||||
|
||||
gui.clearMainView()
|
||||
|
||||
cmd := gui.OSCommand.RunCustomCommand(utils.ApplyTemplate(gui.Config.UserConfig.CommandTemplates.ContainerLogs, container))
|
||||
|
||||
gui.renderLogs(container, gui.Config.UserConfig.CommandTemplates.ContainerLogs, func(cmd *exec.Cmd) {
|
||||
mainView := gui.getMainView()
|
||||
cmd.Stdout = mainView
|
||||
cmd.Stderr = mainView
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gui *Gui) renderLogsForTTYContainer(container *commands.Container) error {
|
||||
gui.renderLogs(container, gui.Config.UserConfig.CommandTemplates.ContainerTTYLogs, func(cmd *exec.Cmd) {
|
||||
// for some reason just saying cmd.Stdout = mainView does not work here as it does for non-tty containers, so we feed it through line by line
|
||||
r, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
gui.ErrorChan <- err
|
||||
}
|
||||
|
||||
go func() {
|
||||
mainView := gui.getMainView()
|
||||
s := bufio.NewScanner(r)
|
||||
s.Split(bufio.ScanLines)
|
||||
for s.Scan() {
|
||||
// I might put a check on the stopped channel here. Would mean more code duplication though
|
||||
mainView.Write(append(s.Bytes(), '\n'))
|
||||
}
|
||||
}()
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gui *Gui) renderLogs(container *commands.Container, template string, setup func(*exec.Cmd)) {
|
||||
gui.T.NewTickerTask(time.Millisecond*200, nil, func(stop, notifyStopped chan struct{}) {
|
||||
gui.clearMainView()
|
||||
|
||||
command := utils.ApplyTemplate(gui.Config.UserConfig.CommandTemplates.ContainerTTYLogs, container)
|
||||
cmd := gui.OSCommand.RunCustomCommand(command)
|
||||
|
||||
setup(cmd)
|
||||
|
||||
cmd.Start()
|
||||
|
||||
|
|
@ -187,59 +217,6 @@ func (gui *Gui) renderLogsForRegularContainer(container *commands.Container) err
|
|||
}
|
||||
}
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gui *Gui) runProcessWithLock(cmd *exec.Cmd) {
|
||||
go gui.T.NewTask(func(stop chan struct{}) {
|
||||
gui.clearMainView()
|
||||
cmd.Start()
|
||||
|
||||
go func() {
|
||||
<-stop
|
||||
cmd.Process.Kill()
|
||||
}()
|
||||
|
||||
cmd.Wait()
|
||||
})
|
||||
}
|
||||
|
||||
func (gui *Gui) renderLogsForTTYContainer(container *commands.Container) error {
|
||||
mainView := gui.getMainView()
|
||||
gui.T.NewTickerTask(time.Millisecond*200, nil, func(stop, notifyStopped chan struct{}) {
|
||||
gui.clearMainView()
|
||||
|
||||
command := utils.ApplyTemplate(gui.Config.UserConfig.CommandTemplates.ContainerTTYLogs, container)
|
||||
cmd := gui.OSCommand.RunCustomCommand(command)
|
||||
|
||||
// for some reason just saying cmd.Stdout = mainView does not work here as it does for non-tty containers, so we feed it through line by line
|
||||
r, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
gui.ErrorChan <- err
|
||||
}
|
||||
|
||||
go func() {
|
||||
s := bufio.NewScanner(r)
|
||||
s.Split(bufio.ScanLines)
|
||||
for s.Scan() {
|
||||
// I might put a check on the stopped channel here. Would mean more code duplication though
|
||||
mainView.Write(append(s.Bytes(), '\n'))
|
||||
}
|
||||
}()
|
||||
|
||||
cmd.Start()
|
||||
|
||||
go func() {
|
||||
<-stop
|
||||
cmd.Process.Kill()
|
||||
return
|
||||
}()
|
||||
|
||||
cmd.Wait()
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gui *Gui) refreshContainersAndServices() error {
|
||||
|
|
@ -275,11 +252,11 @@ func (gui *Gui) refreshContainersAndServices() error {
|
|||
}
|
||||
}
|
||||
|
||||
if len(gui.DockerCommand.Containers) > 0 && gui.State.Panels.Containers.SelectedLine == -1 {
|
||||
if len(gui.DockerCommand.DisplayContainers) > 0 && gui.State.Panels.Containers.SelectedLine == -1 {
|
||||
gui.State.Panels.Containers.SelectedLine = 0
|
||||
}
|
||||
if len(gui.DockerCommand.Containers)-1 < gui.State.Panels.Containers.SelectedLine {
|
||||
gui.State.Panels.Containers.SelectedLine = len(gui.DockerCommand.Containers) - 1
|
||||
if len(gui.DockerCommand.DisplayContainers)-1 < gui.State.Panels.Containers.SelectedLine {
|
||||
gui.State.Panels.Containers.SelectedLine = len(gui.DockerCommand.DisplayContainers) - 1
|
||||
}
|
||||
|
||||
// doing the exact same thing for services
|
||||
|
|
@ -293,7 +270,7 @@ func (gui *Gui) refreshContainersAndServices() error {
|
|||
gui.g.Update(func(g *gocui.Gui) error {
|
||||
containersView.Clear()
|
||||
isFocused := gui.g.CurrentView().Name() == "containers"
|
||||
list, err := utils.RenderList(gui.DockerCommand.Containers, utils.IsFocused(isFocused))
|
||||
list, err := utils.RenderList(gui.DockerCommand.DisplayContainers, utils.IsFocused(isFocused))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -337,7 +314,7 @@ func (gui *Gui) handleContainersNextLine(g *gocui.Gui, v *gocui.View) error {
|
|||
}
|
||||
|
||||
panelState := gui.State.Panels.Containers
|
||||
gui.changeSelectedLine(&panelState.SelectedLine, len(gui.DockerCommand.Containers), false)
|
||||
gui.changeSelectedLine(&panelState.SelectedLine, len(gui.DockerCommand.DisplayContainers), false)
|
||||
|
||||
return gui.handleContainerSelect(gui.g, v)
|
||||
}
|
||||
|
|
@ -348,7 +325,7 @@ func (gui *Gui) handleContainersPrevLine(g *gocui.Gui, v *gocui.View) error {
|
|||
}
|
||||
|
||||
panelState := gui.State.Panels.Containers
|
||||
gui.changeSelectedLine(&panelState.SelectedLine, len(gui.DockerCommand.Containers), true)
|
||||
gui.changeSelectedLine(&panelState.SelectedLine, len(gui.DockerCommand.DisplayContainers), true)
|
||||
|
||||
return gui.handleContainerSelect(gui.g, v)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,7 +164,11 @@ func (gui *Gui) layout(g *gocui.Gui) error {
|
|||
return err
|
||||
}
|
||||
containersView.Highlight = true
|
||||
containersView.Title = gui.Tr.ContainersTitle
|
||||
if gui.Config.UserConfig.Gui.ShowAllContainers {
|
||||
containersView.Title = gui.Tr.ContainersTitle
|
||||
} else {
|
||||
containersView.Title = gui.Tr.StandaloneContainersTitle
|
||||
}
|
||||
containersView.FgColor = gocui.ColorWhite
|
||||
|
||||
gui.focusPoint(0, gui.State.Panels.Containers.SelectedLine, len(gui.DockerCommand.Containers), containersView)
|
||||
|
|
|
|||
|
|
@ -57,16 +57,16 @@ func (gui *Gui) runCommand() error {
|
|||
gui.Log.Error(err)
|
||||
}
|
||||
|
||||
gui.SubProcess.Stdin = nil
|
||||
gui.SubProcess.Stdout = ioutil.Discard
|
||||
gui.SubProcess.Stderr = ioutil.Discard
|
||||
gui.SubProcess = nil
|
||||
|
||||
signal.Stop(c)
|
||||
|
||||
fmt.Fprintf(os.Stdout, "\n%s", utils.ColoredString(gui.Tr.PressEnterToReturn, color.FgGreen))
|
||||
|
||||
fmt.Scanln() // wait for enter press
|
||||
|
||||
gui.SubProcess.Stdout = ioutil.Discard
|
||||
gui.SubProcess.Stderr = ioutil.Discard
|
||||
gui.SubProcess.Stdin = nil
|
||||
gui.SubProcess = nil
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ type TranslationSet struct {
|
|||
ViewLogs string
|
||||
ServicesTitle string
|
||||
ContainersTitle string
|
||||
StandaloneContainersTitle string
|
||||
ImagesTitle string
|
||||
NoContainers string
|
||||
NoImages string
|
||||
|
|
@ -97,12 +98,13 @@ func englishSet() TranslationSet {
|
|||
AnonymousReportingTitle: "Help make lazydocker better",
|
||||
AnonymousReportingPrompt: "Would you like to enable anonymous reporting data to help improve lazydocker? (enter/esc)",
|
||||
|
||||
StatusTitle: "Status",
|
||||
ServicesTitle: "Services",
|
||||
ContainersTitle: "Containers",
|
||||
ImagesTitle: "Images",
|
||||
CustomCommandTitle: "Custom Command:",
|
||||
ErrorTitle: "Error",
|
||||
StatusTitle: "Status",
|
||||
ServicesTitle: "Services",
|
||||
ContainersTitle: "Containers",
|
||||
StandaloneContainersTitle: "Standalone Containers",
|
||||
ImagesTitle: "Images",
|
||||
CustomCommandTitle: "Custom Command:",
|
||||
ErrorTitle: "Error",
|
||||
|
||||
NoContainers: "No containers",
|
||||
NoImages: "No images",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue