mirror of
https://github.com/jesseduffield/lazydocker.git
synced 2026-07-25 08:31:03 +00:00
visually display context tabs
This commit is contained in:
parent
6cc6f61ad1
commit
1246ac1ad3
6 changed files with 73 additions and 43 deletions
|
|
@ -19,7 +19,11 @@ import (
|
||||||
// list panel functions
|
// list panel functions
|
||||||
|
|
||||||
func (gui *Gui) getContainerContexts() []string {
|
func (gui *Gui) getContainerContexts() []string {
|
||||||
return []string{"logs", "config", "stats"}
|
return []string{"logs", "stats", "config"}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) getContainerContextTitles() []string {
|
||||||
|
return []string{gui.Tr.LogsTitle, gui.Tr.StatsTitle, gui.Tr.ConfigTitle}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) getSelectedContainer(g *gocui.Gui) (*commands.Container, error) {
|
func (gui *Gui) getSelectedContainer(g *gocui.Gui) (*commands.Container, error) {
|
||||||
|
|
@ -80,20 +84,22 @@ func (gui *Gui) handleContainerSelect(g *gocui.Gui, v *gocui.View) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
mainView := gui.getMainView()
|
mainView := gui.getMainView()
|
||||||
|
mainView.Tabs = gui.getContainerContextTitles()
|
||||||
|
mainView.TabIndex = gui.State.Panels.Containers.ContextIndex
|
||||||
|
|
||||||
gui.clearMainView()
|
gui.clearMainView()
|
||||||
|
|
||||||
switch gui.getContainerContexts()[gui.State.Panels.Containers.ContextIndex] {
|
switch gui.getContainerContexts()[gui.State.Panels.Containers.ContextIndex] {
|
||||||
case "logs":
|
case "logs":
|
||||||
if err := gui.renderContainerLogs(mainView, container); err != nil {
|
if err := gui.renderContainerLogs(container); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "config":
|
case "config":
|
||||||
if err := gui.renderContainerConfig(mainView, container); err != nil {
|
if err := gui.renderContainerConfig(container); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "stats":
|
case "stats":
|
||||||
if err := gui.renderContainerStats(mainView, container); err != nil {
|
if err := gui.renderContainerStats(container); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
@ -103,9 +109,10 @@ func (gui *Gui) handleContainerSelect(g *gocui.Gui, v *gocui.View) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) renderContainerConfig(mainView *gocui.View, container *commands.Container) error {
|
func (gui *Gui) renderContainerConfig(container *commands.Container) error {
|
||||||
|
mainView := gui.getMainView()
|
||||||
mainView.Autoscroll = false
|
mainView.Autoscroll = false
|
||||||
mainView.Title = "Config"
|
mainView.Wrap = true
|
||||||
|
|
||||||
data, err := json.MarshalIndent(&container.Details, "", " ")
|
data, err := json.MarshalIndent(&container.Details, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -119,9 +126,9 @@ func (gui *Gui) renderContainerConfig(mainView *gocui.View, container *commands.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) renderContainerStats(mainView *gocui.View, container *commands.Container) error {
|
func (gui *Gui) renderContainerStats(container *commands.Container) error {
|
||||||
|
mainView := gui.getMainView()
|
||||||
mainView.Autoscroll = false
|
mainView.Autoscroll = false
|
||||||
mainView.Title = "Stats"
|
|
||||||
mainView.Wrap = false
|
mainView.Wrap = false
|
||||||
|
|
||||||
return gui.T.NewTickerTask(time.Second, func(stop chan struct{}) { gui.clearMainView() }, func(stop, notifyStopped chan struct{}) {
|
return gui.T.NewTickerTask(time.Second, func(stop chan struct{}) { gui.clearMainView() }, func(stop, notifyStopped chan struct{}) {
|
||||||
|
|
@ -136,9 +143,10 @@ func (gui *Gui) renderContainerStats(mainView *gocui.View, container *commands.C
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) renderContainerLogs(mainView *gocui.View, container *commands.Container) error {
|
func (gui *Gui) renderContainerLogs(container *commands.Container) error {
|
||||||
|
mainView := gui.getMainView()
|
||||||
mainView.Autoscroll = true
|
mainView.Autoscroll = true
|
||||||
mainView.Title = "Logs"
|
mainView.Wrap = true
|
||||||
|
|
||||||
if container.Details.Config.OpenStdin {
|
if container.Details.Config.OpenStdin {
|
||||||
return gui.renderLogsForTTYContainer(container)
|
return gui.renderLogsForTTYContainer(container)
|
||||||
|
|
@ -332,7 +340,7 @@ func (gui *Gui) handleContainersPrevLine(g *gocui.Gui, v *gocui.View) error {
|
||||||
return gui.handleContainerSelect(gui.g, v)
|
return gui.handleContainerSelect(gui.g, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleContainersPrevContext(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) handleContainersNextContext(g *gocui.Gui, v *gocui.View) error {
|
||||||
contexts := gui.getContainerContexts()
|
contexts := gui.getContainerContexts()
|
||||||
if gui.State.Panels.Containers.ContextIndex >= len(contexts)-1 {
|
if gui.State.Panels.Containers.ContextIndex >= len(contexts)-1 {
|
||||||
gui.State.Panels.Containers.ContextIndex = 0
|
gui.State.Panels.Containers.ContextIndex = 0
|
||||||
|
|
@ -345,7 +353,7 @@ func (gui *Gui) handleContainersPrevContext(g *gocui.Gui, v *gocui.View) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleContainersNextContext(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) handleContainersPrevContext(g *gocui.Gui, v *gocui.View) error {
|
||||||
contexts := gui.getContainerContexts()
|
contexts := gui.getContainerContexts()
|
||||||
if gui.State.Panels.Containers.ContextIndex <= 0 {
|
if gui.State.Panels.Containers.ContextIndex <= 0 {
|
||||||
gui.State.Panels.Containers.ContextIndex = len(contexts) - 1
|
gui.State.Panels.Containers.ContextIndex = len(contexts) - 1
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,10 @@ func (gui *Gui) getImageContexts() []string {
|
||||||
return []string{"config"}
|
return []string{"config"}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) getImageContextTitles() []string {
|
||||||
|
return []string{gui.Tr.ConfigTitle}
|
||||||
|
}
|
||||||
|
|
||||||
func (gui *Gui) getSelectedImage(g *gocui.Gui) (*commands.Image, error) {
|
func (gui *Gui) getSelectedImage(g *gocui.Gui) (*commands.Image, error) {
|
||||||
selectedLine := gui.State.Panels.Images.SelectedLine
|
selectedLine := gui.State.Panels.Images.SelectedLine
|
||||||
if selectedLine == -1 {
|
if selectedLine == -1 {
|
||||||
|
|
@ -77,6 +81,8 @@ func (gui *Gui) handleImageSelect(g *gocui.Gui, v *gocui.View) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
mainView := gui.getMainView()
|
mainView := gui.getMainView()
|
||||||
|
mainView.Tabs = gui.getImageContextTitles()
|
||||||
|
mainView.TabIndex = gui.State.Panels.Images.ContextIndex
|
||||||
|
|
||||||
switch gui.getImageContexts()[gui.State.Panels.Images.ContextIndex] {
|
switch gui.getImageContexts()[gui.State.Panels.Images.ContextIndex] {
|
||||||
case "config":
|
case "config":
|
||||||
|
|
@ -107,7 +113,6 @@ func (gui *Gui) renderImageConfig(mainView *gocui.View, image *commands.Image) e
|
||||||
|
|
||||||
mainView.Autoscroll = false
|
mainView.Autoscroll = false
|
||||||
mainView.Wrap = false
|
mainView.Wrap = false
|
||||||
mainView.Title = "Config"
|
|
||||||
|
|
||||||
gui.renderString(gui.g, "main", output)
|
gui.renderString(gui.g, "main", output)
|
||||||
})
|
})
|
||||||
|
|
@ -188,7 +193,7 @@ func (gui *Gui) handleImagePress(g *gocui.Gui, v *gocui.View) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleImagesPrevContext(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) handleImagesNextContext(g *gocui.Gui, v *gocui.View) error {
|
||||||
contexts := gui.getImageContexts()
|
contexts := gui.getImageContexts()
|
||||||
if gui.State.Panels.Images.ContextIndex >= len(contexts)-1 {
|
if gui.State.Panels.Images.ContextIndex >= len(contexts)-1 {
|
||||||
gui.State.Panels.Images.ContextIndex = 0
|
gui.State.Panels.Images.ContextIndex = 0
|
||||||
|
|
@ -201,7 +206,7 @@ func (gui *Gui) handleImagesPrevContext(g *gocui.Gui, v *gocui.View) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleImagesNextContext(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) handleImagesPrevContext(g *gocui.Gui, v *gocui.View) error {
|
||||||
contexts := gui.getImageContexts()
|
contexts := gui.getImageContexts()
|
||||||
if gui.State.Panels.Images.ContextIndex <= 0 {
|
if gui.State.Panels.Images.ContextIndex <= 0 {
|
||||||
gui.State.Panels.Images.ContextIndex = len(contexts) - 1
|
gui.State.Panels.Images.ContextIndex = len(contexts) - 1
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,11 @@ import (
|
||||||
// list panel functions
|
// list panel functions
|
||||||
|
|
||||||
func (gui *Gui) getServiceContexts() []string {
|
func (gui *Gui) getServiceContexts() []string {
|
||||||
return []string{"logs", "config", "stats"}
|
return []string{"logs", "stats", "config"}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) getServiceContextTitles() []string {
|
||||||
|
return []string{gui.Tr.LogsTitle, gui.Tr.StatsTitle, gui.Tr.ConfigTitle}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) getSelectedService() (*commands.Service, error) {
|
func (gui *Gui) getSelectedService() (*commands.Service, error) {
|
||||||
|
|
@ -73,17 +77,20 @@ func (gui *Gui) handleServiceSelect(g *gocui.Gui, v *gocui.View) error {
|
||||||
|
|
||||||
mainView := gui.getMainView()
|
mainView := gui.getMainView()
|
||||||
|
|
||||||
|
mainView.Tabs = gui.getServiceContextTitles()
|
||||||
|
mainView.TabIndex = gui.State.Panels.Services.ContextIndex
|
||||||
|
|
||||||
switch gui.getServiceContexts()[gui.State.Panels.Services.ContextIndex] {
|
switch gui.getServiceContexts()[gui.State.Panels.Services.ContextIndex] {
|
||||||
case "logs":
|
case "logs":
|
||||||
if err := gui.renderServiceLogs(mainView, service); err != nil {
|
if err := gui.renderServiceLogs(service); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "config":
|
case "config":
|
||||||
if err := gui.renderServiceConfig(mainView, service); err != nil {
|
if err := gui.renderServiceConfig(service); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "stats":
|
case "stats":
|
||||||
if err := gui.renderServiceStats(mainView, service); err != nil {
|
if err := gui.renderServiceStats(service); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
@ -93,9 +100,10 @@ func (gui *Gui) handleServiceSelect(g *gocui.Gui, v *gocui.View) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) renderServiceConfig(mainView *gocui.View, service *commands.Service) error {
|
func (gui *Gui) renderServiceConfig(service *commands.Service) error {
|
||||||
|
mainView := gui.getMainView()
|
||||||
mainView.Autoscroll = false
|
mainView.Autoscroll = false
|
||||||
mainView.Title = "Config"
|
mainView.Wrap = true
|
||||||
|
|
||||||
go gui.T.NewTask(func(stop chan struct{}) {
|
go gui.T.NewTask(func(stop chan struct{}) {
|
||||||
// TODO: actually show service config
|
// TODO: actually show service config
|
||||||
|
|
@ -110,15 +118,15 @@ func (gui *Gui) renderServiceConfig(mainView *gocui.View, service *commands.Serv
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) renderServiceStats(mainView *gocui.View, service *commands.Service) error {
|
func (gui *Gui) renderServiceStats(service *commands.Service) error {
|
||||||
if service.Container == nil {
|
if service.Container == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return gui.renderContainerStats(mainView, service.Container)
|
return gui.renderContainerStats(service.Container)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) renderServiceLogs(mainView *gocui.View, service *commands.Service) error {
|
func (gui *Gui) renderServiceLogs(service *commands.Service) error {
|
||||||
service, err := gui.getSelectedService()
|
service, err := gui.getSelectedService()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -131,7 +139,7 @@ func (gui *Gui) renderServiceLogs(mainView *gocui.View, service *commands.Servic
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return gui.renderContainerLogs(gui.getMainView(), service.Container)
|
return gui.renderContainerLogs(service.Container)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleServicesNextLine(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) handleServicesNextLine(g *gocui.Gui, v *gocui.View) error {
|
||||||
|
|
@ -156,7 +164,7 @@ func (gui *Gui) handleServicesPrevLine(g *gocui.Gui, v *gocui.View) error {
|
||||||
return gui.handleServiceSelect(gui.g, v)
|
return gui.handleServiceSelect(gui.g, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleServicesPrevContext(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) handleServicesNextContext(g *gocui.Gui, v *gocui.View) error {
|
||||||
contexts := gui.getServiceContexts()
|
contexts := gui.getServiceContexts()
|
||||||
if gui.State.Panels.Services.ContextIndex >= len(contexts)-1 {
|
if gui.State.Panels.Services.ContextIndex >= len(contexts)-1 {
|
||||||
gui.State.Panels.Services.ContextIndex = 0
|
gui.State.Panels.Services.ContextIndex = 0
|
||||||
|
|
@ -169,7 +177,7 @@ func (gui *Gui) handleServicesPrevContext(g *gocui.Gui, v *gocui.View) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleServicesNextContext(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) handleServicesPrevContext(g *gocui.Gui, v *gocui.View) error {
|
||||||
contexts := gui.getServiceContexts()
|
contexts := gui.getServiceContexts()
|
||||||
if gui.State.Panels.Services.ContextIndex <= 0 {
|
if gui.State.Panels.Services.ContextIndex <= 0 {
|
||||||
gui.State.Panels.Services.ContextIndex = len(contexts) - 1
|
gui.State.Panels.Services.ContextIndex = len(contexts) - 1
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,10 @@ func (gui *Gui) getStatusContexts() []string {
|
||||||
return []string{"logs", "credits"}
|
return []string{"logs", "credits"}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) getStatusContextTitles() []string {
|
||||||
|
return []string{gui.Tr.LogsTitle, gui.Tr.CreditsTitle}
|
||||||
|
}
|
||||||
|
|
||||||
func (gui *Gui) refreshStatus() error {
|
func (gui *Gui) refreshStatus() error {
|
||||||
v := gui.getStatusView()
|
v := gui.getStatusView()
|
||||||
|
|
||||||
|
|
@ -43,6 +47,10 @@ func (gui *Gui) handleStatusSelect(g *gocui.Gui, v *gocui.View) error {
|
||||||
|
|
||||||
gui.clearMainView()
|
gui.clearMainView()
|
||||||
|
|
||||||
|
mainView := gui.getMainView()
|
||||||
|
mainView.Tabs = gui.getStatusContextTitles()
|
||||||
|
mainView.TabIndex = gui.State.Panels.Status.ContextIndex
|
||||||
|
|
||||||
switch gui.getStatusContexts()[gui.State.Panels.Status.ContextIndex] {
|
switch gui.getStatusContexts()[gui.State.Panels.Status.ContextIndex] {
|
||||||
case "credits":
|
case "credits":
|
||||||
if err := gui.renderCredits(); err != nil {
|
if err := gui.renderCredits(); err != nil {
|
||||||
|
|
@ -62,7 +70,7 @@ func (gui *Gui) handleStatusSelect(g *gocui.Gui, v *gocui.View) error {
|
||||||
func (gui *Gui) renderCredits() error {
|
func (gui *Gui) renderCredits() error {
|
||||||
mainView := gui.getMainView()
|
mainView := gui.getMainView()
|
||||||
mainView.Autoscroll = false
|
mainView.Autoscroll = false
|
||||||
mainView.Title = "about"
|
mainView.Wrap = true
|
||||||
|
|
||||||
dashboardString := strings.Join(
|
dashboardString := strings.Join(
|
||||||
[]string{
|
[]string{
|
||||||
|
|
@ -83,7 +91,7 @@ func (gui *Gui) renderCredits() error {
|
||||||
func (gui *Gui) renderAllLogs() error {
|
func (gui *Gui) renderAllLogs() error {
|
||||||
mainView := gui.getMainView()
|
mainView := gui.getMainView()
|
||||||
mainView.Autoscroll = true
|
mainView.Autoscroll = true
|
||||||
mainView.Title = "logs"
|
mainView.Wrap = true
|
||||||
|
|
||||||
go gui.T.NewTask(func(stop chan struct{}) {
|
go gui.T.NewTask(func(stop chan struct{}) {
|
||||||
gui.clearMainView()
|
gui.clearMainView()
|
||||||
|
|
@ -130,7 +138,7 @@ func lazydockerTitle() string {
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleStatusPrevContext(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) handleStatusNextContext(g *gocui.Gui, v *gocui.View) error {
|
||||||
contexts := gui.getStatusContexts()
|
contexts := gui.getStatusContexts()
|
||||||
if gui.State.Panels.Status.ContextIndex >= len(contexts)-1 {
|
if gui.State.Panels.Status.ContextIndex >= len(contexts)-1 {
|
||||||
gui.State.Panels.Status.ContextIndex = 0
|
gui.State.Panels.Status.ContextIndex = 0
|
||||||
|
|
@ -143,7 +151,7 @@ func (gui *Gui) handleStatusPrevContext(g *gocui.Gui, v *gocui.View) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleStatusNextContext(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) handleStatusPrevContext(g *gocui.Gui, v *gocui.View) error {
|
||||||
contexts := gui.getStatusContexts()
|
contexts := gui.getStatusContexts()
|
||||||
if gui.State.Panels.Status.ContextIndex <= 0 {
|
if gui.State.Panels.Status.ContextIndex <= 0 {
|
||||||
gui.State.Panels.Status.ContextIndex = len(contexts) - 1
|
gui.State.Panels.Status.ContextIndex = len(contexts) - 1
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,11 @@ type TranslationSet struct {
|
||||||
StopService string
|
StopService string
|
||||||
PressEnterToReturn string
|
PressEnterToReturn string
|
||||||
ViewRestartOptions string
|
ViewRestartOptions string
|
||||||
|
|
||||||
|
LogsTitle string
|
||||||
|
ConfigTitle string
|
||||||
|
StatsTitle string
|
||||||
|
CreditsTitle string
|
||||||
}
|
}
|
||||||
|
|
||||||
func englishSet() TranslationSet {
|
func englishSet() TranslationSet {
|
||||||
|
|
@ -105,6 +110,10 @@ func englishSet() TranslationSet {
|
||||||
ImagesTitle: "Images",
|
ImagesTitle: "Images",
|
||||||
CustomCommandTitle: "Custom Command:",
|
CustomCommandTitle: "Custom Command:",
|
||||||
ErrorTitle: "Error",
|
ErrorTitle: "Error",
|
||||||
|
LogsTitle: "Logs",
|
||||||
|
ConfigTitle: "Config",
|
||||||
|
StatsTitle: "Stats",
|
||||||
|
CreditsTitle: "About",
|
||||||
|
|
||||||
NoContainers: "No containers",
|
NoContainers: "No containers",
|
||||||
NoImages: "No images",
|
NoImages: "No images",
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,9 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import "fmt"
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cmd := exec.Command("docker", strings.Split("logs --follow 29754cb1ab9a", " ")...)
|
var arr []string
|
||||||
|
arr = nil
|
||||||
cmd.Stdout = os.Stdout
|
fmt.Println(len(arr))
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
|
|
||||||
cmd.Start()
|
|
||||||
cmd.Wait()
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue