lazydocker/pkg/commands/image.go
Charalambos Emmanouilidis a0819d6b91 Fix color contrast for better readability on dark backgrounds
Changed FgBlue to FgCyan in multiple locations to improve text visibility
on terminals with dark blue ANSI colors. This affects image history display,
service status indicators, container states, keyboard shortcuts, and command output.

Fixes #685
2025-12-16 16:53:57 +02:00

143 lines
3.4 KiB
Go

package commands
import (
"context"
"strings"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/client"
"github.com/fatih/color"
"github.com/jesseduffield/lazydocker/pkg/utils"
"github.com/samber/lo"
"github.com/sirupsen/logrus"
)
// Image : A docker Image
type Image struct {
Name string
Tag string
ID string
Image image.Summary
Client *client.Client
OSCommand *OSCommand
Log *logrus.Entry
DockerCommand LimitedDockerCommand
}
// Remove removes the image
func (i *Image) Remove(options image.RemoveOptions) error {
if _, err := i.Client.ImageRemove(context.Background(), i.ID, options); err != nil {
return err
}
return nil
}
func getHistoryResponseItemDisplayStrings(layer image.HistoryResponseItem) []string {
tag := ""
if len(layer.Tags) > 0 {
tag = layer.Tags[0]
}
id := strings.TrimPrefix(layer.ID, "sha256:")
if len(id) > 10 {
id = id[0:10]
}
idColor := color.FgWhite
if id == "<missing>" {
idColor = color.FgCyan
}
dockerFileCommandPrefix := "/bin/sh -c #(nop) "
createdBy := layer.CreatedBy
if strings.Contains(layer.CreatedBy, dockerFileCommandPrefix) {
createdBy = strings.Trim(strings.TrimPrefix(layer.CreatedBy, dockerFileCommandPrefix), " ")
split := strings.Split(createdBy, " ")
createdBy = utils.ColoredString(split[0], color.FgYellow) + " " + strings.Join(split[1:], " ")
}
createdBy = strings.Replace(createdBy, "\t", " ", -1)
size := utils.FormatBinaryBytes(int(layer.Size))
sizeColor := color.FgWhite
if size == "0B" {
sizeColor = color.FgCyan
}
return []string{
utils.ColoredString(id, idColor),
utils.ColoredString(tag, color.FgGreen),
utils.ColoredString(size, sizeColor),
createdBy,
}
}
// RenderHistory renders the history of the image
func (i *Image) RenderHistory() (string, error) {
history, err := i.Client.ImageHistory(context.Background(), i.ID)
if err != nil {
return "", err
}
tableBody := lo.Map(history, func(layer image.HistoryResponseItem, _ int) []string {
return getHistoryResponseItemDisplayStrings(layer)
})
headers := [][]string{{"ID", "TAG", "SIZE", "COMMAND"}}
table := append(headers, tableBody...)
return utils.RenderTable(table)
}
// RefreshImages returns a slice of docker images
func (c *DockerCommand) RefreshImages() ([]*Image, error) {
images, err := c.Client.ImageList(context.Background(), image.ListOptions{})
if err != nil {
return nil, err
}
ownImages := make([]*Image, len(images))
for i, img := range images {
firstTag := ""
tags := img.RepoTags
if len(tags) > 0 {
firstTag = tags[0]
}
nameParts := strings.Split(firstTag, ":")
tag := ""
name := "none"
if len(nameParts) > 1 {
tag = nameParts[len(nameParts)-1]
name = strings.Join(nameParts[:len(nameParts)-1], ":")
for prefix, replacement := range c.Config.UserConfig.Replacements.ImageNamePrefixes {
if strings.HasPrefix(name, prefix) {
name = strings.Replace(name, prefix, replacement, 1)
break
}
}
}
ownImages[i] = &Image{
ID: img.ID,
Name: name,
Tag: tag,
Image: img,
Client: c.Client,
OSCommand: c.OSCommand,
Log: c.Log,
DockerCommand: c,
}
}
return ownImages, nil
}
// PruneImages prunes images
func (c *DockerCommand) PruneImages() error {
_, err := c.Client.ImagesPrune(context.Background(), filters.Args{})
return err
}