much more stuff

This commit is contained in:
Jesse Duffield 2019-06-09 00:08:22 +10:00
parent 9a5a01dfbd
commit b65df625f4
8 changed files with 151 additions and 7 deletions

View file

@ -254,7 +254,17 @@ type ContainerCliStat struct {
// GetDisplayStrings returns the dispaly string of Container
func (c *Container) GetDisplayStrings(isFocused bool) []string {
return []string{utils.ColoredString(c.Container.State, c.GetColor()), utils.ColoredString(c.Name, color.FgWhite), c.GetDisplayCPUPerc()}
return []string{c.GetDisplayStatus(), utils.ColoredString(c.Name, color.FgWhite), c.GetDisplayCPUPerc()}
}
// GetDisplayStatus returns the colored status of the container
func (c *Container) GetDisplayStatus() string {
state := c.Container.State
if c.Container.State == "exited" {
state += " (" + strconv.Itoa(c.Details.State.ExitCode) + ")"
}
return utils.ColoredString(state, c.GetColor())
}
// GetDisplayCPUPerc colors the cpu percentage based on how extreme it is
@ -292,6 +302,9 @@ func (c *Container) ProducingLogs() bool {
func (c *Container) GetColor() color.Attribute {
switch c.Container.State {
case "exited":
if c.Details.State.ExitCode == 0 {
return color.FgBlue
}
return color.FgRed
case "created":
return color.FgCyan

View file

@ -9,6 +9,7 @@ import (
"regexp"
"strings"
"sync"
"syscall"
"time"
"github.com/go-errors/errors"
@ -366,3 +367,13 @@ func (c *OSCommand) PipeCommands(commandStrings ...string) error {
}
return nil
}
// Kill kills a process. If the process has Setpgid == true, then we have anticipated that it might spawn its own child processes, so we've given it a process group ID (PGID) equal to its process id (PID) and given its child processes will inherit the PGID, we can kill that group, rather than killing the process itself.
func (c *OSCommand) Kill(cmd *exec.Cmd) error {
if cmd.SysProcAttr != nil && cmd.SysProcAttr.Setpgid == true {
// minus sign means we're talking about a PGID as opposed to a PID
return syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
}
return cmd.Process.Kill()
}

View file

@ -27,7 +27,7 @@ func (s *Service) GetDisplayStrings(isFocused bool) []string {
}
cont := s.Container
return []string{utils.ColoredString(cont.Container.State, cont.GetColor()), utils.ColoredString(s.Name, color.FgWhite), cont.GetDisplayCPUPerc()}
return []string{cont.GetDisplayStatus(), utils.ColoredString(s.Name, color.FgWhite), cont.GetDisplayCPUPerc()}
}
// Remove removes the service's containers
@ -68,7 +68,6 @@ func (s *Service) ViewLogs() (*exec.Cmd, error) {
// so long as this is commented in, the child process does not receive the interrupt
cmd.SysProcAttr = &syscall.SysProcAttr{
Setpgid: true,
Pgid: 0,
}
return cmd, nil

View file

@ -110,6 +110,7 @@ type CommandTemplatesConfig struct {
RebuildService string `yaml:"rebuildService,omitempty"`
ContainerLogs string `yaml:"containerLogs,omitempty"`
ContainerTTYLogs string `yaml:"containerTTYLogs,omitempty"`
AllLogs string `yaml:"allLogs,omitempty"`
}
type OSConfig struct {
@ -164,6 +165,7 @@ func GetDefaultConfig() UserConfig {
ServiceLogs: "apdev logs {{ .Name }}",
ContainerLogs: "docker logs --timestamps --follow --tail=100 {{ .ID }}",
ContainerTTYLogs: "docker logs --follow --tail=100 {{ .ID }}",
AllLogs: "apdev logs --tail=100",
},
OS: GetPlatformDefaultConfig(),
Update: UpdateConfig{

View file

@ -77,6 +77,10 @@ type containerPanelState struct {
ContextIndex int // for specifying if you are looking at logs/stats/config/etc
}
type statusState struct {
ContextIndex int // for specifying if you are looking at credits/logs
}
type menuPanelState struct {
SelectedLine int
}
@ -96,6 +100,7 @@ type panelStates struct {
Menu *menuPanelState
Main *mainPanelState
Images *imagePanelState
Status *statusState
}
type guiState struct {
@ -121,6 +126,7 @@ func NewGui(log *logrus.Entry, dockerCommand *commands.DockerCommand, oSCommand
Main: &mainPanelState{
ObjectKey: "",
},
Status: &statusState{ContextIndex: 0},
},
}

View file

@ -133,6 +133,20 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
Handler: gui.handleOpenConfig,
Description: gui.Tr.OpenConfig,
},
{
ViewName: "status",
Key: '[',
Modifier: gocui.ModNone,
Handler: gui.handleStatusPrevContext,
Description: gui.Tr.PreviousContext,
},
{
ViewName: "status",
Key: ']',
Modifier: gocui.ModNone,
Handler: gui.handleStatusNextContext,
Description: gui.Tr.NextContext,
},
{
ViewName: "menu",
Key: gocui.KeyEsc,

View file

@ -3,10 +3,16 @@ package gui
import (
"fmt"
"strings"
"syscall"
"github.com/go-errors/errors"
"github.com/jesseduffield/gocui"
)
func (gui *Gui) getStatusContexts() []string {
return []string{"logs", "credits"}
}
func (gui *Gui) refreshStatus() error {
v := gui.getStatusView()
@ -28,6 +34,36 @@ func (gui *Gui) handleStatusSelect(g *gocui.Gui, v *gocui.View) error {
return err
}
key := gui.getStatusContexts()[gui.State.Panels.Status.ContextIndex]
if gui.State.Panels.Main.ObjectKey == key {
return nil
} else {
gui.State.Panels.Main.ObjectKey = key
}
gui.clearMainView()
switch gui.getStatusContexts()[gui.State.Panels.Status.ContextIndex] {
case "credits":
if err := gui.renderCredits(); err != nil {
return err
}
case "logs":
if err := gui.renderAllLogs(); err != nil {
return err
}
default:
return errors.New("Unknown context for status panel")
}
return nil
}
func (gui *Gui) renderCredits() error {
mainView := gui.getMainView()
mainView.Autoscroll = false
mainView.Title = "about"
dashboardString := strings.Join(
[]string{
lazydockerTitle(),
@ -37,7 +73,40 @@ func (gui *Gui) handleStatusSelect(g *gocui.Gui, v *gocui.View) error {
"Raise an Issue: https://github.com/jesseduffield/lazydocker/issues",
}, "\n\n")
return gui.renderString(g, "main", dashboardString)
go gui.T.NewTask(func(stop chan struct{}) {
gui.renderString(gui.g, "main", dashboardString)
})
return nil
}
func (gui *Gui) renderAllLogs() error {
mainView := gui.getMainView()
mainView.Autoscroll = true
mainView.Title = "logs"
go gui.T.NewTask(func(stop chan struct{}) {
gui.clearMainView()
cmd := gui.OSCommand.RunCustomCommand(gui.Config.UserConfig.CommandTemplates.AllLogs)
cmd.Stdout = mainView
cmd.Stderr = mainView
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
cmd.Start()
go func() {
<-stop
if err := gui.OSCommand.Kill(cmd); err != nil {
gui.Log.Error(err)
}
}()
cmd.Wait()
})
return nil
}
func (gui *Gui) handleOpenConfig(g *gocui.Gui, v *gocui.View) error {
@ -60,3 +129,29 @@ func lazydockerTitle() string {
|___/
`
}
func (gui *Gui) handleStatusPrevContext(g *gocui.Gui, v *gocui.View) error {
contexts := gui.getStatusContexts()
if gui.State.Panels.Status.ContextIndex >= len(contexts)-1 {
gui.State.Panels.Status.ContextIndex = 0
} else {
gui.State.Panels.Status.ContextIndex++
}
gui.handleStatusSelect(gui.g, v)
return nil
}
func (gui *Gui) handleStatusNextContext(g *gocui.Gui, v *gocui.View) error {
contexts := gui.getStatusContexts()
if gui.State.Panels.Status.ContextIndex <= 0 {
gui.State.Panels.Status.ContextIndex = len(contexts) - 1
} else {
gui.State.Panels.Status.ContextIndex--
}
gui.handleStatusSelect(gui.g, v)
return nil
}

View file

@ -21,6 +21,10 @@ func (gui *Gui) RunWithSubprocesses() error {
if err == gocui.ErrQuit {
break
} else if err == gui.Errors.ErrSubProcess {
// preparing the state for when we return
gui.State.PreviousView = gui.currentViewName()
gui.State.Panels.Main.ObjectKey = ""
if err := gui.runCommand(); err != nil {
return err
}
@ -33,8 +37,6 @@ func (gui *Gui) RunWithSubprocesses() error {
}
func (gui *Gui) runCommand() error {
gui.State.PreviousView = gui.currentViewName()
gui.SubProcess.Stdout = os.Stdout
gui.SubProcess.Stderr = os.Stdout
gui.SubProcess.Stdin = os.Stdin
@ -46,7 +48,9 @@ func (gui *Gui) runCommand() error {
<-c
signal.Stop(c)
gui.SubProcess.Process.Kill()
if err := gui.OSCommand.Kill(gui.SubProcess); err != nil {
gui.Log.Error(err)
}
}()
fmt.Fprintf(os.Stdout, "\n%s\n\n", utils.ColoredString("+ "+strings.Join(gui.SubProcess.Args, " "), color.FgBlue))