mirror of
https://github.com/jesseduffield/lazydocker.git
synced 2026-07-22 15:11:02 +00:00
- All the checks are in the `waitForTerminalSpace` function - It tries to run the program directly if the width is positive - It then sleeps 50 milliseconds the first time if the width is zero - If after the first sleep, the terminal width is still zero, it prints the waiting time to stderr and will keep on doing so with increasing sleep times.
121 lines
2.8 KiB
Go
121 lines
2.8 KiB
Go
package app
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
"golang.org/x/crypto/ssh/terminal"
|
|
|
|
"github.com/jesseduffield/lazydocker/pkg/commands"
|
|
"github.com/jesseduffield/lazydocker/pkg/config"
|
|
"github.com/jesseduffield/lazydocker/pkg/gui"
|
|
"github.com/jesseduffield/lazydocker/pkg/i18n"
|
|
"github.com/jesseduffield/lazydocker/pkg/log"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// App struct
|
|
type App struct {
|
|
closers []io.Closer
|
|
|
|
Config *config.AppConfig
|
|
Log *logrus.Entry
|
|
OSCommand *commands.OSCommand
|
|
DockerCommand *commands.DockerCommand
|
|
Gui *gui.Gui
|
|
Tr *i18n.TranslationSet
|
|
ErrorChan chan error
|
|
}
|
|
|
|
// NewApp bootstrap a new application
|
|
func NewApp(config *config.AppConfig) (*App, error) {
|
|
app := &App{
|
|
closers: []io.Closer{},
|
|
Config: config,
|
|
ErrorChan: make(chan error),
|
|
}
|
|
var err error
|
|
app.Log = log.NewLogger(config, "23432119147a4367abf7c0de2aa99a2d")
|
|
app.Tr = i18n.NewTranslationSet(app.Log)
|
|
app.OSCommand = commands.NewOSCommand(app.Log, config)
|
|
|
|
// here is the place to make use of the docker-compose.yml file in the current directory
|
|
|
|
app.DockerCommand, err = commands.NewDockerCommand(app.Log, app.OSCommand, app.Tr, app.Config, app.ErrorChan)
|
|
if err != nil {
|
|
return app, err
|
|
}
|
|
app.Gui, err = gui.NewGui(app.Log, app.DockerCommand, app.OSCommand, app.Tr, config, app.ErrorChan)
|
|
if err != nil {
|
|
return app, err
|
|
}
|
|
return app, nil
|
|
}
|
|
|
|
func (app *App) Run() error {
|
|
err := waitForTerminalSpace()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = app.Gui.RunWithSubprocesses()
|
|
return err
|
|
}
|
|
|
|
func waitForTerminalSpace() error {
|
|
// before we do anything, we need to check that we have some window space available
|
|
tStart := time.Now()
|
|
count := 0
|
|
for {
|
|
width, _, err := terminal.GetSize(int(os.Stdin.Fd()))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if width != 0 {
|
|
return nil
|
|
}
|
|
count++
|
|
time.Sleep(time.Millisecond * 50 * time.Duration(count))
|
|
if count > 1 {
|
|
fmt.Fprintf(os.Stderr, "waited %s for available terminal space\n", time.Since(tStart))
|
|
}
|
|
}
|
|
}
|
|
|
|
// Close closes any resources
|
|
func (app *App) Close() error {
|
|
for _, closer := range app.closers {
|
|
err := closer.Close()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type errorMapping struct {
|
|
originalError string
|
|
newError string
|
|
}
|
|
|
|
// KnownError takes an error and tells us whether it's an error that we know about where we can print a nicely formatted version of it rather than panicking with a stack trace
|
|
func (app *App) KnownError(err error) (string, bool) {
|
|
errorMessage := err.Error()
|
|
|
|
mappings := []errorMapping{
|
|
{
|
|
originalError: "Got permission denied while trying to connect to the Docker daemon socket",
|
|
newError: app.Tr.CannotAccessDockerSocketError,
|
|
},
|
|
}
|
|
|
|
for _, mapping := range mappings {
|
|
if strings.Contains(errorMessage, mapping.originalError) {
|
|
return mapping.newError, true
|
|
}
|
|
}
|
|
|
|
return "", false
|
|
}
|