diff --git a/pkg/commands/docker.go b/pkg/commands/docker.go index b0b4d402..45280ee4 100644 --- a/pkg/commands/docker.go +++ b/pkg/commands/docker.go @@ -46,13 +46,20 @@ func NewDockerCommand(log *logrus.Entry, osCommand *OSCommand, tr *i18n.Translat return nil, err } + inDockerComposeProject := true + err = osCommand.RunCommand(config.UserConfig.CommandTemplates.CheckDockerComposeConfig) + if err != nil { + inDockerComposeProject = false + log.Warn(err.Error()) + } + return &DockerCommand{ Log: log, OSCommand: osCommand, Tr: tr, Config: config, Client: cli, - InDockerComposeProject: true, // TODO: determine this at startup + InDockerComposeProject: inDockerComposeProject, ErrorChan: errorChan, }, nil } diff --git a/pkg/config/app_config.go b/pkg/config/app_config.go index 9ddd9a54..73996a7d 100644 --- a/pkg/config/app_config.go +++ b/pkg/config/app_config.go @@ -110,12 +110,13 @@ type CommandTemplatesConfig struct { RebuildService string `yaml:"rebuildService,omitempty"` // ViewContainerLogs is for viewing the container logs in a subprocess. We have this as a separate command in case you want to show all the logs rather than just tail them for the sake of reducing CPU load when in the lazydocker GUI - ViewContainerLogs string `yaml:"viewContainerLogs,omitempty"` - ContainerLogs string `yaml:"containerLogs,omitempty"` - ContainerTTYLogs string `yaml:"containerTTYLogs,omitempty"` - AllLogs string `yaml:"allLogs,omitempty"` - ViewAllLogs string `yaml:"viewAlLogs,omitempty"` - DockerComposeConfig string `yaml:"dockerComposeConfig,omitempty"` + ViewContainerLogs string `yaml:"viewContainerLogs,omitempty"` + ContainerLogs string `yaml:"containerLogs,omitempty"` + ContainerTTYLogs string `yaml:"containerTTYLogs,omitempty"` + AllLogs string `yaml:"allLogs,omitempty"` + ViewAllLogs string `yaml:"viewAlLogs,omitempty"` + DockerComposeConfig string `yaml:"dockerComposeConfig,omitempty"` + CheckDockerComposeConfig string `yaml:"checkDockerComposeConfig,omitempty"` } type OSConfig struct { @@ -163,17 +164,18 @@ func GetDefaultConfig() UserConfig { Reporting: "undetermined", ConfirmOnQuit: false, CommandTemplates: CommandTemplatesConfig{ - RestartService: "docker-compose restart {{ .Name }}", - RebuildService: "docker-compose up -d --build {{ .Name }}", - DockerCompose: "apdev compose", - StopService: "apdev stop {{ .Name }}", - ServiceLogs: "apdev logs {{ .Name }}", - ContainerLogs: "docker logs --timestamps --follow --tail=100 {{ .ID }}", - ViewContainerLogs: "docker logs --timestamps --follow --tail=100 {{ .ID }}", - ContainerTTYLogs: "docker logs --follow --tail=100 {{ .ID }}", - AllLogs: "apdev logs --tail=100", - ViewAllLogs: "apdev logs", - DockerComposeConfig: "apdev compose config", + RestartService: "docker-compose restart {{ .Name }}", + RebuildService: "docker-compose up -d --build {{ .Name }}", + DockerCompose: "docker-compose", + StopService: "docker-compose stop {{ .Name }}", + ServiceLogs: "docker-compose logs {{ .Name }}", + AllLogs: "docker-compose logs --tail=100", + ViewAllLogs: "docker-compose logs", + DockerComposeConfig: "docker-compose config", + CheckDockerComposeConfig: "docker-compose config --quiet", + ContainerLogs: "docker logs --timestamps --follow --tail=100 {{ .ID }}", + ViewContainerLogs: "docker logs --timestamps --follow --tail=100 {{ .ID }}", + ContainerTTYLogs: "docker logs --follow --tail=100 {{ .ID }}", }, OS: GetPlatformDefaultConfig(), Update: UpdateConfig{ diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 221f6a83..9b7bddd9 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -67,6 +67,7 @@ type Gui struct { waitForIntro sync.WaitGroup T *tasks.TaskManager ErrorChan chan error + CyclableViews []string } type servicePanelState struct { @@ -122,9 +123,13 @@ type guiState struct { // NewGui builds a new gui handler func NewGui(log *logrus.Entry, dockerCommand *commands.DockerCommand, oSCommand *commands.OSCommand, tr *i18n.TranslationSet, config *config.AppConfig, errorChan chan error) (*Gui, error) { + previousView := "containers" + if dockerCommand.InDockerComposeProject { + previousView = "services" + } initialState := guiState{ - PreviousView: "services", + PreviousView: previousView, Platform: *oSCommand.Platform, Panels: &panelStates{ Services: &servicePanelState{SelectedLine: -1, ContextIndex: 0}, @@ -139,6 +144,11 @@ func NewGui(log *logrus.Entry, dockerCommand *commands.DockerCommand, oSCommand }, } + cyclableViews := []string{"status", "containers", "images", "volumes"} + if dockerCommand.InDockerComposeProject { + cyclableViews = []string{"status", "services", "containers", "images", "volumes"} + } + gui := &Gui{ Log: log, DockerCommand: dockerCommand, @@ -150,6 +160,7 @@ func NewGui(log *logrus.Entry, dockerCommand *commands.DockerCommand, oSCommand statusManager: &statusManager{}, T: tasks.NewTaskManager(log), ErrorChan: errorChan, + CyclableViews: cyclableViews, } gui.GenerateSentinelErrors() diff --git a/pkg/gui/layout.go b/pkg/gui/layout.go index 78875270..e83e8ced 100644 --- a/pkg/gui/layout.go +++ b/pkg/gui/layout.go @@ -78,7 +78,7 @@ func (gui *Gui) layout(g *gocui.Gui) error { if currView != nil { viewName := currView.Name() usePreviouseView := true - for _, view := range cyclableViews { + for _, view := range gui.CyclableViews { if view == viewName { currentCyclebleView = viewName usePreviouseView = false @@ -92,15 +92,26 @@ func (gui *Gui) layout(g *gocui.Gui) error { usableSpace := height - 4 - tallPanels := 4 - - vHeights := map[string]int{ - "status": 3, - "services": usableSpace/tallPanels + usableSpace%tallPanels, - "containers": usableSpace / tallPanels, - "images": usableSpace / tallPanels, - "volumes": usableSpace / tallPanels, - "options": 1, + tallPanels := 3 + var vHeights map[string]int + if gui.DockerCommand.InDockerComposeProject { + tallPanels++ + vHeights = map[string]int{ + "status": 3, + "services": usableSpace/tallPanels + usableSpace%tallPanels, + "containers": usableSpace / tallPanels, + "images": usableSpace / tallPanels, + "volumes": usableSpace / tallPanels, + "options": 1, + } + } else { + vHeights = map[string]int{ + "status": 3, + "containers": usableSpace/tallPanels + usableSpace%tallPanels, + "images": usableSpace / tallPanels, + "volumes": usableSpace / tallPanels, + "options": 1, + } } if height < 28 { @@ -110,12 +121,14 @@ func (gui *Gui) layout(g *gocui.Gui) error { } vHeights = map[string]int{ "status": defaultHeight, - "services": defaultHeight, "containers": defaultHeight, "images": defaultHeight, "volumes": defaultHeight, "options": defaultHeight, } + if gui.DockerCommand.InDockerComposeProject { + vHeights["services"] = defaultHeight + } vHeights[currentCyclebleView] = height - defaultHeight*tallPanels - 1 } @@ -148,25 +161,30 @@ func (gui *Gui) layout(g *gocui.Gui) error { v.FgColor = gocui.ColorWhite } - servicesView, err := g.SetViewBeneath("services", "status", vHeights["services"]) - if err != nil { - if err.Error() != "unknown view" { - return err - } - servicesView.Highlight = true - servicesView.Title = gui.Tr.ServicesTitle - servicesView.FgColor = gocui.ColorWhite + var servicesView *gocui.View + aboveContainersView := "status" + if gui.DockerCommand.InDockerComposeProject { + aboveContainersView = "services" + servicesView, err = g.SetViewBeneath("services", "status", vHeights["services"]) + if err != nil { + if err.Error() != "unknown view" { + return err + } + servicesView.Highlight = true + servicesView.Title = gui.Tr.ServicesTitle + servicesView.FgColor = gocui.ColorWhite - gui.focusPoint(0, gui.State.Panels.Services.SelectedLine, len(gui.DockerCommand.Services), servicesView) + gui.focusPoint(0, gui.State.Panels.Services.SelectedLine, len(gui.DockerCommand.Services), servicesView) + } } - containersView, err := g.SetViewBeneath("containers", "services", vHeights["containers"]) + containersView, err := g.SetViewBeneath("containers", aboveContainersView, vHeights["containers"]) if err != nil { if err.Error() != "unknown view" { return err } containersView.Highlight = true - if gui.Config.UserConfig.Gui.ShowAllContainers { + if gui.Config.UserConfig.Gui.ShowAllContainers || !gui.DockerCommand.InDockerComposeProject { containersView.Title = gui.Tr.ContainersTitle } else { containersView.Title = gui.Tr.StandaloneContainersTitle @@ -255,6 +273,7 @@ func (gui *Gui) layout(g *gocui.Gui) error { lineCount int } + // TODO: find out if I should add the services view to this. listViews := map[*gocui.View]listViewState{ containersView: {selectedLine: gui.State.Panels.Containers.SelectedLine, lineCount: len(gui.DockerCommand.Containers)}, imagesView: {selectedLine: gui.State.Panels.Images.SelectedLine, lineCount: len(gui.DockerCommand.Images)}, diff --git a/pkg/gui/status_panel.go b/pkg/gui/status_panel.go index 33b5c839..0be05354 100644 --- a/pkg/gui/status_panel.go +++ b/pkg/gui/status_panel.go @@ -9,11 +9,17 @@ import ( ) func (gui *Gui) getStatusContexts() []string { - return []string{"logs", "credits", "config"} + if gui.DockerCommand.InDockerComposeProject { + return []string{"logs", "credits", "config"} + } + return []string{"credits"} } func (gui *Gui) getStatusContextTitles() []string { - return []string{gui.Tr.LogsTitle, gui.Tr.CreditsTitle, gui.Tr.ConfigTitle} + if gui.DockerCommand.InDockerComposeProject { + return []string{gui.Tr.LogsTitle, gui.Tr.CreditsTitle, gui.Tr.ConfigTitle} + } + return []string{gui.Tr.CreditsTitle} } func (gui *Gui) refreshStatus() error { @@ -71,20 +77,20 @@ func (gui *Gui) handleStatusSelect(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) renderCredits() error { - mainView := gui.getMainView() - mainView.Autoscroll = false - mainView.Wrap = true - - dashboardString := strings.Join( - []string{ - lazydockerTitle(), - "Copyright (c) 2019 Jesse Duffield", - "Keybindings: https://github.com/jesseduffield/lazydocker/blob/master/docs/keybindings", - "Config Options: https://github.com/jesseduffield/lazydocker/blob/master/docs/Config.md", - "Raise an Issue: https://github.com/jesseduffield/lazydocker/issues", - }, "\n\n") - go gui.T.NewTask(func(stop chan struct{}) { + mainView := gui.getMainView() + mainView.Autoscroll = false + mainView.Wrap = true + + dashboardString := strings.Join( + []string{ + lazydockerTitle(), + "Copyright (c) 2019 Jesse Duffield", + "Keybindings: https://github.com/jesseduffield/lazydocker/blob/master/docs/keybindings", + "Config Options: https://github.com/jesseduffield/lazydocker/blob/master/docs/Config.md", + "Raise an Issue: https://github.com/jesseduffield/lazydocker/issues", + }, "\n\n") + gui.renderString(gui.g, "main", dashboardString) }) @@ -92,11 +98,11 @@ func (gui *Gui) renderCredits() error { } func (gui *Gui) renderAllLogs() error { - mainView := gui.getMainView() - mainView.Autoscroll = true - mainView.Wrap = true - go gui.T.NewTask(func(stop chan struct{}) { + mainView := gui.getMainView() + mainView.Autoscroll = true + mainView.Wrap = true + gui.clearMainView() cmd := gui.OSCommand.RunCustomCommand(gui.Config.UserConfig.CommandTemplates.AllLogs) @@ -121,11 +127,11 @@ func (gui *Gui) renderAllLogs() error { } func (gui *Gui) renderDockerComposeConfig() error { - mainView := gui.getMainView() - mainView.Autoscroll = false - mainView.Wrap = true - go gui.T.NewTask(func(stop chan struct{}) { + mainView := gui.getMainView() + mainView.Autoscroll = false + mainView.Wrap = true + config := gui.DockerCommand.DockerComposeConfig() gui.renderString(gui.g, "main", config) }) diff --git a/pkg/gui/view_helpers.go b/pkg/gui/view_helpers.go index 49d4ef97..d0dba4e1 100644 --- a/pkg/gui/view_helpers.go +++ b/pkg/gui/view_helpers.go @@ -10,8 +10,6 @@ import ( "github.com/spkg/bom" ) -var cyclableViews = []string{"status", "services", "containers", "images", "volumes"} - func (gui *Gui) refreshSidePanels(g *gocui.Gui) error { // not refreshing containers and services here given that we do it every few milliseconds anyway if err := gui.refreshImages(); err != nil { @@ -26,16 +24,16 @@ func (gui *Gui) refreshSidePanels(g *gocui.Gui) error { func (gui *Gui) nextView(g *gocui.Gui, v *gocui.View) error { var focusedViewName string - if v == nil || v.Name() == cyclableViews[len(cyclableViews)-1] { - focusedViewName = cyclableViews[0] + if v == nil || v.Name() == gui.CyclableViews[len(gui.CyclableViews)-1] { + focusedViewName = gui.CyclableViews[0] } else { viewName := v.Name() - for i := range cyclableViews { - if viewName == cyclableViews[i] { - focusedViewName = cyclableViews[i+1] + for i := range gui.CyclableViews { + if viewName == gui.CyclableViews[i] { + focusedViewName = gui.CyclableViews[i+1] break } - if i == len(cyclableViews)-1 { + if i == len(gui.CyclableViews)-1 { gui.Log.Info("not in list of views") return nil } @@ -51,16 +49,16 @@ func (gui *Gui) nextView(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) previousView(g *gocui.Gui, v *gocui.View) error { var focusedViewName string - if v == nil || v.Name() == cyclableViews[0] { - focusedViewName = cyclableViews[len(cyclableViews)-1] + if v == nil || v.Name() == gui.CyclableViews[0] { + focusedViewName = gui.CyclableViews[len(gui.CyclableViews)-1] } else { viewName := v.Name() - for i := range cyclableViews { - if viewName == cyclableViews[i] { - focusedViewName = cyclableViews[i-1] + for i := range gui.CyclableViews { + if viewName == gui.CyclableViews[i] { + focusedViewName = gui.CyclableViews[i-1] break } - if i == len(cyclableViews)-1 { + if i == len(gui.CyclableViews)-1 { gui.Log.Info("not in list of views") return nil }