From 1488bfbcd44fc15f164717228856c252a8644527 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sun, 19 May 2019 00:19:27 +1000 Subject: [PATCH] separate refreshing of container panel from refreshing of main view using a key based on container id and context name --- pkg/gui/containers_panel.go | 35 ++++++++++++++++------------- pkg/gui/gui.go | 45 +++++++++++++------------------------ pkg/gui/view_helpers.go | 4 +++- 3 files changed, 37 insertions(+), 47 deletions(-) diff --git a/pkg/gui/containers_panel.go b/pkg/gui/containers_panel.go index af5b8814..c42e52d1 100644 --- a/pkg/gui/containers_panel.go +++ b/pkg/gui/containers_panel.go @@ -44,7 +44,7 @@ func (gui *Gui) handleContainersFocus(g *gocui.Gui, v *gocui.View) error { newSelectedLine := cy - oy if newSelectedLine > len(gui.State.Containers)-1 || len(utils.Decolorise(gui.State.Containers[newSelectedLine].Name)) < cx { - return gui.handleContainerSelect(gui.g, v, false) + return gui.handleContainerSelect(gui.g, v) } gui.State.Panels.Containers.SelectedLine = newSelectedLine @@ -52,11 +52,11 @@ func (gui *Gui) handleContainersFocus(g *gocui.Gui, v *gocui.View) error { if prevSelectedLine == newSelectedLine && gui.currentViewName() == v.Name() { return gui.handleContainerPress(gui.g, v) } else { - return gui.handleContainerSelect(gui.g, v, true) + return gui.handleContainerSelect(gui.g, v) } } -func (gui *Gui) handleContainerSelect(g *gocui.Gui, v *gocui.View, alreadySelected bool) error { +func (gui *Gui) handleContainerSelect(g *gocui.Gui, v *gocui.View) error { if _, err := gui.g.SetCurrentView(v.Name()); err != nil { return err } @@ -69,14 +69,21 @@ func (gui *Gui) handleContainerSelect(g *gocui.Gui, v *gocui.View, alreadySelect return gui.renderString(g, "main", gui.Tr.SLocalize("NoChangedContainers")) } + key := container.ID + "-" + gui.getContainerContexts()[gui.State.Panels.Containers.ContextIndex] + if gui.State.Panels.Main.ObjectKey == key { + return nil + } else { + gui.State.Panels.Main.ObjectKey = key + } + if err := gui.focusPoint(0, gui.State.Panels.Containers.SelectedLine, len(gui.State.Containers), v); err != nil { return err } mainView := gui.getMainView() - gui.State.MainWriterID++ - writerID := gui.State.MainWriterID + gui.State.Panels.Main.WriterID++ + writerID := gui.State.Panels.Main.WriterID mainView.Clear() mainView.SetOrigin(0, 0) @@ -150,7 +157,7 @@ func (gui *Gui) renderStats(mainView *gocui.View, container *commands.Container, gui.createErrorPanel(gui.g, err.Error()) } - if gui.State.MainWriterID != writerID { + if gui.State.Panels.Main.WriterID != writerID { stream.Body.Close() return } @@ -177,7 +184,7 @@ func (gui *Gui) renderLogs(mainView *gocui.View, container *commands.Container, go func() { for { time.Sleep(time.Second / 100) - if gui.State.MainWriterID != writerID { + if gui.State.Panels.Main.WriterID != writerID { cmd.Process.Kill() return } @@ -188,8 +195,6 @@ func (gui *Gui) renderLogs(mainView *gocui.View, container *commands.Container, } func (gui *Gui) refreshContainers() error { - selectedContainer, _ := gui.getSelectedContainer(gui.g) - containersView := gui.getContainersView() if containersView == nil { // if the containersView hasn't been instantiated yet we just return @@ -217,9 +222,7 @@ func (gui *Gui) refreshContainers() error { fmt.Fprint(containersView, list) if containersView == g.CurrentView() { - newSelectedContainer, _ := gui.getSelectedContainer(gui.g) - alreadySelected := newSelectedContainer.Name == selectedContainer.Name - return gui.handleContainerSelect(g, containersView, alreadySelected) + return gui.handleContainerSelect(g, containersView) } return nil }) @@ -246,7 +249,7 @@ func (gui *Gui) handleContainersNextLine(g *gocui.Gui, v *gocui.View) error { panelState := gui.State.Panels.Containers gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Containers), false) - return gui.handleContainerSelect(gui.g, v, false) + return gui.handleContainerSelect(gui.g, v) } func (gui *Gui) handleContainersPrevLine(g *gocui.Gui, v *gocui.View) error { @@ -257,7 +260,7 @@ func (gui *Gui) handleContainersPrevLine(g *gocui.Gui, v *gocui.View) error { panelState := gui.State.Panels.Containers gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Containers), true) - return gui.handleContainerSelect(gui.g, v, false) + return gui.handleContainerSelect(gui.g, v) } func (gui *Gui) handleContainerPress(g *gocui.Gui, v *gocui.View) error { @@ -272,7 +275,7 @@ func (gui *Gui) handleContainersPrevContext(g *gocui.Gui, v *gocui.View) error { gui.State.Panels.Containers.ContextIndex++ } - gui.handleContainerSelect(gui.g, v, false) + gui.handleContainerSelect(gui.g, v) return nil } @@ -285,7 +288,7 @@ func (gui *Gui) handleContainersNextContext(g *gocui.Gui, v *gocui.View) error { gui.State.Panels.Containers.ContextIndex-- } - gui.handleContainerSelect(gui.g, v, false) + gui.handleContainerSelect(gui.g, v) return nil } diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 71a9a44d..8ebacecc 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -82,9 +82,15 @@ type menuPanelState struct { SelectedLine int } +type mainPanelState struct { + ObjectKey string + WriterID int +} + type panelStates struct { Containers *containerPanelState Menu *menuPanelState + Main *mainPanelState } type guiState struct { @@ -95,7 +101,6 @@ type guiState struct { Updating bool Panels *panelStates SubProcessOutput string - MainWriterID int } // NewGui builds a new gui handler @@ -108,8 +113,11 @@ func NewGui(log *logrus.Entry, dockerCommand *commands.DockerCommand, oSCommand Panels: &panelStates{ Containers: &containerPanelState{SelectedLine: -1, ContextIndex: 0}, Menu: &menuPanelState{SelectedLine: 0}, + Main: &mainPanelState{ + WriterID: 0, + ObjectKey: "", + }, }, - MainWriterID: 0, } gui := &Gui{ @@ -200,7 +208,7 @@ func (gui *Gui) onFocusLost(v *gocui.View, newView *gocui.View) error { return nil } if v.Name() == "containers" { - gui.State.MainWriterID++ + gui.State.Panels.Main.WriterID++ } gui.Log.Info(v.Name() + " focus lost") return nil @@ -479,6 +487,7 @@ func (gui *Gui) Run() error { gui.waitForIntro.Wait() gui.goEvery(time.Millisecond*50, gui.renderAppStatus) gui.goEvery(time.Millisecond*30, gui.reRenderMain) + gui.goEvery(time.Millisecond*500, gui.refreshContainers) }() g.SetManager(gocui.ManagerFunc(gui.layout), gocui.ManagerFunc(gui.getFocusLayout())) @@ -530,34 +539,10 @@ func (gui *Gui) RunWithSubprocesses() error { // adapted from https://blog.kowalczyk.info/article/wOYk/advanced-command-execution-in-go-with-osexec.html func (gui *Gui) runCommand(cmd *exec.Cmd) (string, error) { var stdoutBuf bytes.Buffer - stdoutIn, _ := cmd.StdoutPipe() - stderrIn, _ := cmd.StderrPipe() + cmd.Stdout = io.MultiWriter(os.Stdout, &stdoutBuf) + cmd.Stderr = io.MultiWriter(os.Stderr, &stdoutBuf) - stdout := io.MultiWriter(os.Stdout, &stdoutBuf) - stderr := io.MultiWriter(os.Stderr, &stdoutBuf) - err := cmd.Start() - if err != nil { - return "", err - } - - var wg sync.WaitGroup - wg.Add(1) - - go func() { - if _, err := io.Copy(stdout, stdoutIn); err != nil { - gui.Log.Error(err) - } - - wg.Done() - }() - - if _, err := io.Copy(stderr, stderrIn); err != nil { - return "", err - } - - wg.Wait() - - if err := cmd.Wait(); err != nil { + if err := cmd.Run(); err != nil { // not handling the error explicitly because usually we're going to see it // in the output anyway gui.Log.Error(err) diff --git a/pkg/gui/view_helpers.go b/pkg/gui/view_helpers.go index 6be81f32..ce16f9ba 100644 --- a/pkg/gui/view_helpers.go +++ b/pkg/gui/view_helpers.go @@ -40,6 +40,7 @@ func (gui *Gui) nextView(g *gocui.Gui, v *gocui.View) error { if err != nil { panic(err) } + gui.State.Panels.Main.ObjectKey = "" return gui.switchFocus(g, v, focusedView) } @@ -64,6 +65,7 @@ func (gui *Gui) previousView(g *gocui.Gui, v *gocui.View) error { if err != nil { panic(err) } + gui.State.Panels.Main.ObjectKey = "" return gui.switchFocus(g, v, focusedView) } @@ -74,7 +76,7 @@ func (gui *Gui) newLineFocused(g *gocui.Gui, v *gocui.View) error { case "status": return gui.handleStatusSelect(g, v) case "containers": - return gui.handleContainerSelect(g, v, true) + return gui.handleContainerSelect(g, v) case "confirmation": return nil case "main":