separate refreshing of container panel from refreshing of main view using a key based on container id and context name

This commit is contained in:
Jesse Duffield 2019-05-19 00:19:27 +10:00
parent cf8e1f0195
commit 1488bfbcd4
3 changed files with 37 additions and 47 deletions

View file

@ -44,7 +44,7 @@ func (gui *Gui) handleContainersFocus(g *gocui.Gui, v *gocui.View) error {
newSelectedLine := cy - oy newSelectedLine := cy - oy
if newSelectedLine > len(gui.State.Containers)-1 || len(utils.Decolorise(gui.State.Containers[newSelectedLine].Name)) < cx { 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 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() { if prevSelectedLine == newSelectedLine && gui.currentViewName() == v.Name() {
return gui.handleContainerPress(gui.g, v) return gui.handleContainerPress(gui.g, v)
} else { } 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 { if _, err := gui.g.SetCurrentView(v.Name()); err != nil {
return err 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")) 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 { if err := gui.focusPoint(0, gui.State.Panels.Containers.SelectedLine, len(gui.State.Containers), v); err != nil {
return err return err
} }
mainView := gui.getMainView() mainView := gui.getMainView()
gui.State.MainWriterID++ gui.State.Panels.Main.WriterID++
writerID := gui.State.MainWriterID writerID := gui.State.Panels.Main.WriterID
mainView.Clear() mainView.Clear()
mainView.SetOrigin(0, 0) mainView.SetOrigin(0, 0)
@ -150,7 +157,7 @@ func (gui *Gui) renderStats(mainView *gocui.View, container *commands.Container,
gui.createErrorPanel(gui.g, err.Error()) gui.createErrorPanel(gui.g, err.Error())
} }
if gui.State.MainWriterID != writerID { if gui.State.Panels.Main.WriterID != writerID {
stream.Body.Close() stream.Body.Close()
return return
} }
@ -177,7 +184,7 @@ func (gui *Gui) renderLogs(mainView *gocui.View, container *commands.Container,
go func() { go func() {
for { for {
time.Sleep(time.Second / 100) time.Sleep(time.Second / 100)
if gui.State.MainWriterID != writerID { if gui.State.Panels.Main.WriterID != writerID {
cmd.Process.Kill() cmd.Process.Kill()
return return
} }
@ -188,8 +195,6 @@ func (gui *Gui) renderLogs(mainView *gocui.View, container *commands.Container,
} }
func (gui *Gui) refreshContainers() error { func (gui *Gui) refreshContainers() error {
selectedContainer, _ := gui.getSelectedContainer(gui.g)
containersView := gui.getContainersView() containersView := gui.getContainersView()
if containersView == nil { if containersView == nil {
// if the containersView hasn't been instantiated yet we just return // if the containersView hasn't been instantiated yet we just return
@ -217,9 +222,7 @@ func (gui *Gui) refreshContainers() error {
fmt.Fprint(containersView, list) fmt.Fprint(containersView, list)
if containersView == g.CurrentView() { if containersView == g.CurrentView() {
newSelectedContainer, _ := gui.getSelectedContainer(gui.g) return gui.handleContainerSelect(g, containersView)
alreadySelected := newSelectedContainer.Name == selectedContainer.Name
return gui.handleContainerSelect(g, containersView, alreadySelected)
} }
return nil return nil
}) })
@ -246,7 +249,7 @@ func (gui *Gui) handleContainersNextLine(g *gocui.Gui, v *gocui.View) error {
panelState := gui.State.Panels.Containers panelState := gui.State.Panels.Containers
gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Containers), false) 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 { 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 panelState := gui.State.Panels.Containers
gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Containers), true) 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 { 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.State.Panels.Containers.ContextIndex++
} }
gui.handleContainerSelect(gui.g, v, false) gui.handleContainerSelect(gui.g, v)
return nil return nil
} }
@ -285,7 +288,7 @@ func (gui *Gui) handleContainersNextContext(g *gocui.Gui, v *gocui.View) error {
gui.State.Panels.Containers.ContextIndex-- gui.State.Panels.Containers.ContextIndex--
} }
gui.handleContainerSelect(gui.g, v, false) gui.handleContainerSelect(gui.g, v)
return nil return nil
} }

View file

@ -82,9 +82,15 @@ type menuPanelState struct {
SelectedLine int SelectedLine int
} }
type mainPanelState struct {
ObjectKey string
WriterID int
}
type panelStates struct { type panelStates struct {
Containers *containerPanelState Containers *containerPanelState
Menu *menuPanelState Menu *menuPanelState
Main *mainPanelState
} }
type guiState struct { type guiState struct {
@ -95,7 +101,6 @@ type guiState struct {
Updating bool Updating bool
Panels *panelStates Panels *panelStates
SubProcessOutput string SubProcessOutput string
MainWriterID int
} }
// NewGui builds a new gui handler // NewGui builds a new gui handler
@ -108,8 +113,11 @@ func NewGui(log *logrus.Entry, dockerCommand *commands.DockerCommand, oSCommand
Panels: &panelStates{ Panels: &panelStates{
Containers: &containerPanelState{SelectedLine: -1, ContextIndex: 0}, Containers: &containerPanelState{SelectedLine: -1, ContextIndex: 0},
Menu: &menuPanelState{SelectedLine: 0}, Menu: &menuPanelState{SelectedLine: 0},
Main: &mainPanelState{
WriterID: 0,
ObjectKey: "",
},
}, },
MainWriterID: 0,
} }
gui := &Gui{ gui := &Gui{
@ -200,7 +208,7 @@ func (gui *Gui) onFocusLost(v *gocui.View, newView *gocui.View) error {
return nil return nil
} }
if v.Name() == "containers" { if v.Name() == "containers" {
gui.State.MainWriterID++ gui.State.Panels.Main.WriterID++
} }
gui.Log.Info(v.Name() + " focus lost") gui.Log.Info(v.Name() + " focus lost")
return nil return nil
@ -479,6 +487,7 @@ func (gui *Gui) Run() error {
gui.waitForIntro.Wait() gui.waitForIntro.Wait()
gui.goEvery(time.Millisecond*50, gui.renderAppStatus) gui.goEvery(time.Millisecond*50, gui.renderAppStatus)
gui.goEvery(time.Millisecond*30, gui.reRenderMain) gui.goEvery(time.Millisecond*30, gui.reRenderMain)
gui.goEvery(time.Millisecond*500, gui.refreshContainers)
}() }()
g.SetManager(gocui.ManagerFunc(gui.layout), gocui.ManagerFunc(gui.getFocusLayout())) 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 // 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) { func (gui *Gui) runCommand(cmd *exec.Cmd) (string, error) {
var stdoutBuf bytes.Buffer var stdoutBuf bytes.Buffer
stdoutIn, _ := cmd.StdoutPipe() cmd.Stdout = io.MultiWriter(os.Stdout, &stdoutBuf)
stderrIn, _ := cmd.StderrPipe() cmd.Stderr = io.MultiWriter(os.Stderr, &stdoutBuf)
stdout := io.MultiWriter(os.Stdout, &stdoutBuf) if err := cmd.Run(); err != nil {
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 {
// not handling the error explicitly because usually we're going to see it // not handling the error explicitly because usually we're going to see it
// in the output anyway // in the output anyway
gui.Log.Error(err) gui.Log.Error(err)

View file

@ -40,6 +40,7 @@ func (gui *Gui) nextView(g *gocui.Gui, v *gocui.View) error {
if err != nil { if err != nil {
panic(err) panic(err)
} }
gui.State.Panels.Main.ObjectKey = ""
return gui.switchFocus(g, v, focusedView) return gui.switchFocus(g, v, focusedView)
} }
@ -64,6 +65,7 @@ func (gui *Gui) previousView(g *gocui.Gui, v *gocui.View) error {
if err != nil { if err != nil {
panic(err) panic(err)
} }
gui.State.Panels.Main.ObjectKey = ""
return gui.switchFocus(g, v, focusedView) return gui.switchFocus(g, v, focusedView)
} }
@ -74,7 +76,7 @@ func (gui *Gui) newLineFocused(g *gocui.Gui, v *gocui.View) error {
case "status": case "status":
return gui.handleStatusSelect(g, v) return gui.handleStatusSelect(g, v)
case "containers": case "containers":
return gui.handleContainerSelect(g, v, true) return gui.handleContainerSelect(g, v)
case "confirmation": case "confirmation":
return nil return nil
case "main": case "main":