mirror of
https://github.com/jesseduffield/lazydocker.git
synced 2026-07-25 00:21:04 +00:00
lots of changes
This commit is contained in:
parent
2f1c246fd7
commit
2e9a80fe6c
9 changed files with 171 additions and 68 deletions
|
|
@ -162,8 +162,8 @@ func (s *ContainerStats) RenderStats(viewWidth int, cpuUsageHistory []float64, m
|
||||||
fmt.Sprintf(
|
fmt.Sprintf(
|
||||||
"%.2f%% Memory (%s/%s)",
|
"%.2f%% Memory (%s/%s)",
|
||||||
memoryUsageHistory[len(memoryUsageHistory)-1],
|
memoryUsageHistory[len(memoryUsageHistory)-1],
|
||||||
formatBinaryBytes(s.MemoryStats.Usage),
|
utils.FormatBinaryBytes(s.MemoryStats.Usage),
|
||||||
formatBinaryBytes(int(s.MemoryStats.Limit)),
|
utils.FormatBinaryBytes(int(s.MemoryStats.Limit)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
@ -178,8 +178,8 @@ func (s *ContainerStats) RenderStats(viewWidth int, cpuUsageHistory []float64, m
|
||||||
)
|
)
|
||||||
|
|
||||||
pidsCount := fmt.Sprintf("PIDs: %d", s.PidsStats.Current)
|
pidsCount := fmt.Sprintf("PIDs: %d", s.PidsStats.Current)
|
||||||
dataReceived := fmt.Sprintf("Traffic received: %s", formatDecimalBytes(s.Networks.Eth0.RxBytes))
|
dataReceived := fmt.Sprintf("Traffic received: %s", utils.FormatDecimalBytes(s.Networks.Eth0.RxBytes))
|
||||||
dataSent := fmt.Sprintf("Traffic sent: %s", formatDecimalBytes(s.Networks.Eth0.TxBytes))
|
dataSent := fmt.Sprintf("Traffic sent: %s", utils.FormatDecimalBytes(s.Networks.Eth0.TxBytes))
|
||||||
|
|
||||||
originalJSON, err := json.MarshalIndent(s, "", " ")
|
originalJSON, err := json.MarshalIndent(s, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -197,29 +197,3 @@ func (s *ContainerStats) RenderStats(viewWidth int, cpuUsageHistory []float64, m
|
||||||
|
|
||||||
return contents, nil
|
return contents, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatBinaryBytes(b int) string {
|
|
||||||
n := float64(b)
|
|
||||||
units := []string{"B", "kiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}
|
|
||||||
for _, unit := range units {
|
|
||||||
if n > math.Pow(2, 10) {
|
|
||||||
n = n / math.Pow(2, 10)
|
|
||||||
} else {
|
|
||||||
return fmt.Sprintf("%.2f%s", n, unit)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "a lot"
|
|
||||||
}
|
|
||||||
|
|
||||||
func formatDecimalBytes(b int) string {
|
|
||||||
n := float64(b)
|
|
||||||
units := []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
|
|
||||||
for _, unit := range units {
|
|
||||||
if n > math.Pow(10, 3) {
|
|
||||||
n = n / math.Pow(10, 3)
|
|
||||||
} else {
|
|
||||||
return fmt.Sprintf("%.2f%s", n, unit)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "a lot"
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -78,11 +78,6 @@ func (c *DockerCommand) GetImages() ([]*Image, error) {
|
||||||
for i, image := range images {
|
for i, image := range images {
|
||||||
// func (cli *Client) ImageHistory(ctx context.Context, imageID string) ([]image.HistoryResponseItem, error)
|
// func (cli *Client) ImageHistory(ctx context.Context, imageID string) ([]image.HistoryResponseItem, error)
|
||||||
|
|
||||||
history, err := c.Client.ImageHistory(context.Background(), image.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
name := "none"
|
name := "none"
|
||||||
tags := image.RepoTags
|
tags := image.RepoTags
|
||||||
if len(tags) > 0 {
|
if len(tags) > 0 {
|
||||||
|
|
@ -99,7 +94,6 @@ func (c *DockerCommand) GetImages() ([]*Image, error) {
|
||||||
Client: c.Client,
|
Client: c.Client,
|
||||||
OSCommand: c.OSCommand,
|
OSCommand: c.OSCommand,
|
||||||
Log: c.Log,
|
Log: c.Log,
|
||||||
History: history,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@ package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
|
|
@ -16,7 +18,6 @@ type Image struct {
|
||||||
Tag string
|
Tag string
|
||||||
ID string
|
ID string
|
||||||
Image types.ImageSummary
|
Image types.ImageSummary
|
||||||
History []types.ImageHistory
|
|
||||||
Client *client.Client
|
Client *client.Client
|
||||||
OSCommand *OSCommand
|
OSCommand *OSCommand
|
||||||
Log *logrus.Entry
|
Log *logrus.Entry
|
||||||
|
|
@ -24,7 +25,8 @@ type Image struct {
|
||||||
|
|
||||||
// GetDisplayStrings returns the display string of Image
|
// GetDisplayStrings returns the display string of Image
|
||||||
func (i *Image) GetDisplayStrings(isFocused bool) []string {
|
func (i *Image) GetDisplayStrings(isFocused bool) []string {
|
||||||
return []string{utils.ColoredString(i.Name, color.FgWhite), utils.ColoredString(i.Tag, color.FgWhite)}
|
|
||||||
|
return []string{utils.ColoredString(i.Name, color.FgWhite), utils.ColoredString(i.Tag, color.FgWhite), utils.FormatDecimalBytes(int(i.Image.Size))}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove removes the image
|
// Remove removes the image
|
||||||
|
|
@ -35,3 +37,66 @@ func (i *Image) Remove(options types.ImageRemoveOptions) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Layer is a layer in an image's history
|
||||||
|
type Layer struct {
|
||||||
|
types.ImageHistory
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDisplayStrings returns the array of strings describing the layer
|
||||||
|
func (l *Layer) GetDisplayStrings(isFocused bool) []string {
|
||||||
|
tag := ""
|
||||||
|
if len(l.Tags) > 0 {
|
||||||
|
tag = l.Tags[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
id := strings.TrimPrefix(l.ID, "sha256:")
|
||||||
|
if len(id) > 10 {
|
||||||
|
id = id[0:10]
|
||||||
|
}
|
||||||
|
idColor := color.FgWhite
|
||||||
|
if id == "<missing>" {
|
||||||
|
idColor = color.FgBlack
|
||||||
|
}
|
||||||
|
|
||||||
|
dockerFileCommandPrefix := "/bin/sh -c #(nop) "
|
||||||
|
createdBy := l.CreatedBy
|
||||||
|
if strings.Contains(l.CreatedBy, dockerFileCommandPrefix) {
|
||||||
|
createdBy = strings.Trim(strings.TrimPrefix(l.CreatedBy, dockerFileCommandPrefix), " ")
|
||||||
|
split := strings.Split(createdBy, " ")
|
||||||
|
createdBy = utils.ColoredString(split[0], color.FgYellow) + " " + strings.Join(split[1:], " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
createdBy = strings.ReplaceAll(createdBy, "\t", " ")
|
||||||
|
|
||||||
|
size := utils.FormatBinaryBytes(int(l.Size))
|
||||||
|
sizeColor := color.FgWhite
|
||||||
|
if size == "0B" {
|
||||||
|
sizeColor = color.FgBlack
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
i.Log.Warn(spew.Sdump(history))
|
||||||
|
|
||||||
|
layers := make([]*Layer, len(history))
|
||||||
|
for i, layer := range history {
|
||||||
|
layers[i] = &Layer{layer}
|
||||||
|
}
|
||||||
|
|
||||||
|
return utils.RenderList(layers, utils.WithHeader([]string{"ID", "TAG", "SIZE", "COMMAND"}))
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -215,7 +215,7 @@ func (gui *Gui) refreshContainers() error {
|
||||||
|
|
||||||
containersView.Clear()
|
containersView.Clear()
|
||||||
isFocused := gui.g.CurrentView().Name() == "containers"
|
isFocused := gui.g.CurrentView().Name() == "containers"
|
||||||
list, err := utils.RenderList(gui.State.Containers, isFocused)
|
list, err := utils.RenderList(gui.State.Containers, utils.IsFocused(isFocused))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
package gui
|
package gui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
|
|
@ -96,21 +97,25 @@ func (gui *Gui) handleImageSelect(g *gocui.Gui, v *gocui.View) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) renderImageConfig(mainView *gocui.View, Image *commands.Image, writerID int) error {
|
func (gui *Gui) renderImageConfig(mainView *gocui.View, image *commands.Image, writerID int) error {
|
||||||
mainView.Autoscroll = false
|
mainView.Autoscroll = false
|
||||||
|
mainView.Wrap = false
|
||||||
mainView.Title = "Config"
|
mainView.Title = "Config"
|
||||||
|
|
||||||
data, err := json.MarshalIndent(&Image.Image, "", " ")
|
output := ""
|
||||||
|
output += utils.WithPadding("ID: ", 10) + image.Image.ID + "\n"
|
||||||
|
output += utils.WithPadding("Tags: ", 10) + utils.ColoredString(strings.Join(image.Image.RepoTags, ", "), color.FgGreen) + "\n"
|
||||||
|
output += utils.WithPadding("Size: ", 10) + utils.FormatDecimalBytes(int(image.Image.Size)) + "\n"
|
||||||
|
output += utils.WithPadding("Created: ", 10) + fmt.Sprintf("%v", time.Unix(image.Image.Created, 0).Format(time.RFC1123)) + "\n"
|
||||||
|
|
||||||
|
history, err := image.RenderHistory()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
historyData, err := json.MarshalIndent(&Image.History, "", " ")
|
output += "\n\n" + history
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
gui.renderString(gui.g, "main", string(data)+"\n"+string(historyData))
|
gui.renderString(gui.g, "main", output)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -136,7 +141,7 @@ func (gui *Gui) refreshImages() error {
|
||||||
|
|
||||||
ImagesView.Clear()
|
ImagesView.Clear()
|
||||||
isFocused := gui.g.CurrentView().Name() == "Images"
|
isFocused := gui.g.CurrentView().Name() == "Images"
|
||||||
list, err := utils.RenderList(gui.State.Images, isFocused)
|
list, err := utils.RenderList(gui.State.Images, utils.IsFocused(isFocused))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ func (gui *Gui) handleMenuClose(g *gocui.Gui, v *gocui.View) error {
|
||||||
func (gui *Gui) createMenu(title string, items interface{}, itemCount int, handlePress func(int) error) error {
|
func (gui *Gui) createMenu(title string, items interface{}, itemCount int, handlePress func(int) error) error {
|
||||||
isFocused := gui.g.CurrentView().Name() == "menu"
|
isFocused := gui.g.CurrentView().Name() == "menu"
|
||||||
gui.State.MenuItemCount = itemCount
|
gui.State.MenuItemCount = itemCount
|
||||||
list, err := utils.RenderList(items, isFocused)
|
list, err := utils.RenderList(items, utils.IsFocused(isFocused))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,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 = ""
|
gui.resetMainView()
|
||||||
return gui.switchFocus(g, v, focusedView)
|
return gui.switchFocus(g, v, focusedView)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -68,10 +68,15 @@ 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 = ""
|
gui.resetMainView()
|
||||||
return gui.switchFocus(g, v, focusedView)
|
return gui.switchFocus(g, v, focusedView)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) resetMainView() {
|
||||||
|
gui.State.Panels.Main.ObjectKey = ""
|
||||||
|
gui.getMainView().Wrap = true
|
||||||
|
}
|
||||||
|
|
||||||
func (gui *Gui) newLineFocused(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) newLineFocused(g *gocui.Gui, v *gocui.View) error {
|
||||||
switch v.Name() {
|
switch v.Name() {
|
||||||
case "menu":
|
case "menu":
|
||||||
|
|
@ -307,7 +312,7 @@ func (gui *Gui) refreshSelectedLine(line *int, total int) {
|
||||||
func (gui *Gui) renderListPanel(v *gocui.View, items interface{}) error {
|
func (gui *Gui) renderListPanel(v *gocui.View, items interface{}) error {
|
||||||
gui.g.Update(func(g *gocui.Gui) error {
|
gui.g.Update(func(g *gocui.Gui) error {
|
||||||
isFocused := gui.g.CurrentView().Name() == v.Name()
|
isFocused := gui.g.CurrentView().Name() == v.Name()
|
||||||
list, err := utils.RenderList(items, isFocused)
|
list, err := utils.RenderList(items, utils.IsFocused(isFocused))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return gui.createErrorPanel(gui.g, err.Error())
|
return gui.createErrorPanel(gui.g, err.Error())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package utils
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -95,10 +96,32 @@ type Displayable interface {
|
||||||
GetDisplayStrings(bool) []string
|
GetDisplayStrings(bool) []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RenderListConfig struct {
|
||||||
|
IsFocused bool
|
||||||
|
Header []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsFocused(isFocused bool) func(c *RenderListConfig) {
|
||||||
|
return func(c *RenderListConfig) {
|
||||||
|
c.IsFocused = isFocused
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithHeader(header []string) func(c *RenderListConfig) {
|
||||||
|
return func(c *RenderListConfig) {
|
||||||
|
c.Header = header
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// RenderList takes a slice of items, confirms they implement the Displayable
|
// RenderList takes a slice of items, confirms they implement the Displayable
|
||||||
// interface, then generates a list of their displaystrings to write to a panel's
|
// interface, then generates a list of their displaystrings to write to a panel's
|
||||||
// buffer
|
// buffer
|
||||||
func RenderList(slice interface{}, isFocused bool) (string, error) {
|
func RenderList(slice interface{}, options ...func(*RenderListConfig)) (string, error) {
|
||||||
|
config := &RenderListConfig{}
|
||||||
|
for _, option := range options {
|
||||||
|
option(config)
|
||||||
|
}
|
||||||
|
|
||||||
s := reflect.ValueOf(slice)
|
s := reflect.ValueOf(slice)
|
||||||
if s.Kind() != reflect.Slice {
|
if s.Kind() != reflect.Slice {
|
||||||
return "", errors.New("RenderList given a non-slice type")
|
return "", errors.New("RenderList given a non-slice type")
|
||||||
|
|
@ -114,19 +137,22 @@ func RenderList(slice interface{}, isFocused bool) (string, error) {
|
||||||
displayables[i] = value
|
displayables[i] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
return renderDisplayableList(displayables, isFocused)
|
return renderDisplayableList(displayables, *config)
|
||||||
}
|
}
|
||||||
|
|
||||||
// renderDisplayableList takes a list of displayable items, obtains their display
|
// renderDisplayableList takes a list of displayable items, obtains their display
|
||||||
// strings via GetDisplayStrings() and then returns a single string containing
|
// strings via GetDisplayStrings() and then returns a single string containing
|
||||||
// each item's string representation on its own line, with appropriate horizontal
|
// each item's string representation on its own line, with appropriate horizontal
|
||||||
// padding between the item's own strings
|
// padding between the item's own strings
|
||||||
func renderDisplayableList(items []Displayable, isFocused bool) (string, error) {
|
func renderDisplayableList(items []Displayable, config RenderListConfig) (string, error) {
|
||||||
if len(items) == 0 {
|
if len(items) == 0 {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
stringArrays := getDisplayStringArrays(items, isFocused)
|
stringArrays := getDisplayStringArrays(items, config.IsFocused)
|
||||||
|
if len(config.Header) > 0 {
|
||||||
|
stringArrays = append([][]string{config.Header}, stringArrays...)
|
||||||
|
}
|
||||||
|
|
||||||
if !displayArraysAligned(stringArrays) {
|
if !displayArraysAligned(stringArrays) {
|
||||||
return "", errors.New("Each item must return the same number of strings to display")
|
return "", errors.New("Each item must return the same number of strings to display")
|
||||||
|
|
@ -228,3 +254,37 @@ func AsJson(i interface{}) string {
|
||||||
bytes, _ := json.MarshalIndent(i, "", " ")
|
bytes, _ := json.MarshalIndent(i, "", " ")
|
||||||
return string(bytes)
|
return string(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FormatBinaryBytes(b int) string {
|
||||||
|
n := float64(b)
|
||||||
|
units := []string{"B", "kiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}
|
||||||
|
for _, unit := range units {
|
||||||
|
if n > math.Pow(2, 10) {
|
||||||
|
n = n / math.Pow(2, 10)
|
||||||
|
} else {
|
||||||
|
val := fmt.Sprintf("%.2f%s", n, unit)
|
||||||
|
if val == "0.00B" {
|
||||||
|
return "0B"
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "a lot"
|
||||||
|
}
|
||||||
|
|
||||||
|
func FormatDecimalBytes(b int) string {
|
||||||
|
n := float64(b)
|
||||||
|
units := []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
|
||||||
|
for _, unit := range units {
|
||||||
|
if n > math.Pow(10, 3) {
|
||||||
|
n = n / math.Pow(10, 3)
|
||||||
|
} else {
|
||||||
|
val := fmt.Sprintf("%.2f%s", n, unit)
|
||||||
|
if val == "0.00B" {
|
||||||
|
return "0B"
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "a lot"
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -246,7 +246,7 @@ func TestGetDisplayStringArrays(t *testing.T) {
|
||||||
func TestRenderDisplayableList(t *testing.T) {
|
func TestRenderDisplayableList(t *testing.T) {
|
||||||
type scenario struct {
|
type scenario struct {
|
||||||
input []Displayable
|
input []Displayable
|
||||||
isFocused bool
|
config RenderListConfig
|
||||||
expectedString string
|
expectedString string
|
||||||
expectedErrorMessage string
|
expectedErrorMessage string
|
||||||
}
|
}
|
||||||
|
|
@ -257,7 +257,7 @@ func TestRenderDisplayableList(t *testing.T) {
|
||||||
Displayable(&myDisplayable{[]string{}}),
|
Displayable(&myDisplayable{[]string{}}),
|
||||||
Displayable(&myDisplayable{[]string{}}),
|
Displayable(&myDisplayable{[]string{}}),
|
||||||
},
|
},
|
||||||
false,
|
RenderListConfig{},
|
||||||
"\n",
|
"\n",
|
||||||
"",
|
"",
|
||||||
},
|
},
|
||||||
|
|
@ -266,7 +266,7 @@ func TestRenderDisplayableList(t *testing.T) {
|
||||||
Displayable(&myDisplayable{[]string{"aa", "b"}}),
|
Displayable(&myDisplayable{[]string{"aa", "b"}}),
|
||||||
Displayable(&myDisplayable{[]string{"c", "d"}}),
|
Displayable(&myDisplayable{[]string{"c", "d"}}),
|
||||||
},
|
},
|
||||||
false,
|
RenderListConfig{},
|
||||||
"aa b\nc d",
|
"aa b\nc d",
|
||||||
"",
|
"",
|
||||||
},
|
},
|
||||||
|
|
@ -275,7 +275,7 @@ func TestRenderDisplayableList(t *testing.T) {
|
||||||
Displayable(&myDisplayable{[]string{"a"}}),
|
Displayable(&myDisplayable{[]string{"a"}}),
|
||||||
Displayable(&myDisplayable{[]string{"b", "c"}}),
|
Displayable(&myDisplayable{[]string{"b", "c"}}),
|
||||||
},
|
},
|
||||||
false,
|
RenderListConfig{},
|
||||||
"",
|
"",
|
||||||
"Each item must return the same number of strings to display",
|
"Each item must return the same number of strings to display",
|
||||||
},
|
},
|
||||||
|
|
@ -284,14 +284,14 @@ func TestRenderDisplayableList(t *testing.T) {
|
||||||
Displayable(&myDisplayable{[]string{"a"}}),
|
Displayable(&myDisplayable{[]string{"a"}}),
|
||||||
Displayable(&myDisplayable{[]string{"b"}}),
|
Displayable(&myDisplayable{[]string{"b"}}),
|
||||||
},
|
},
|
||||||
true,
|
RenderListConfig{IsFocused: true},
|
||||||
"a blah\nb blah",
|
"a blah\nb blah",
|
||||||
"",
|
"",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, s := range scenarios {
|
for _, s := range scenarios {
|
||||||
str, err := renderDisplayableList(s.input, s.isFocused)
|
str, err := renderDisplayableList(s.input, s.config)
|
||||||
assert.EqualValues(t, s.expectedString, str)
|
assert.EqualValues(t, s.expectedString, str)
|
||||||
if s.expectedErrorMessage != "" {
|
if s.expectedErrorMessage != "" {
|
||||||
assert.EqualError(t, err, s.expectedErrorMessage)
|
assert.EqualError(t, err, s.expectedErrorMessage)
|
||||||
|
|
@ -305,7 +305,7 @@ func TestRenderDisplayableList(t *testing.T) {
|
||||||
func TestRenderList(t *testing.T) {
|
func TestRenderList(t *testing.T) {
|
||||||
type scenario struct {
|
type scenario struct {
|
||||||
input interface{}
|
input interface{}
|
||||||
isFocused bool
|
options []func(*RenderListConfig)
|
||||||
expectedString string
|
expectedString string
|
||||||
expectedErrorMessage string
|
expectedErrorMessage string
|
||||||
}
|
}
|
||||||
|
|
@ -316,7 +316,7 @@ func TestRenderList(t *testing.T) {
|
||||||
{[]string{"aa", "b"}},
|
{[]string{"aa", "b"}},
|
||||||
{[]string{"c", "d"}},
|
{[]string{"c", "d"}},
|
||||||
},
|
},
|
||||||
false,
|
nil,
|
||||||
"aa b\nc d",
|
"aa b\nc d",
|
||||||
"",
|
"",
|
||||||
},
|
},
|
||||||
|
|
@ -325,13 +325,13 @@ func TestRenderList(t *testing.T) {
|
||||||
{},
|
{},
|
||||||
{},
|
{},
|
||||||
},
|
},
|
||||||
false,
|
nil,
|
||||||
"",
|
"",
|
||||||
"item does not implement the Displayable interface",
|
"item does not implement the Displayable interface",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
&myStruct{},
|
&myStruct{},
|
||||||
false,
|
nil,
|
||||||
"",
|
"",
|
||||||
"RenderList given a non-slice type",
|
"RenderList given a non-slice type",
|
||||||
},
|
},
|
||||||
|
|
@ -339,14 +339,14 @@ func TestRenderList(t *testing.T) {
|
||||||
[]*myDisplayable{
|
[]*myDisplayable{
|
||||||
{[]string{"a"}},
|
{[]string{"a"}},
|
||||||
},
|
},
|
||||||
true,
|
[]func(*RenderListConfig){IsFocused(true)},
|
||||||
"a blah",
|
"a blah",
|
||||||
"",
|
"",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, s := range scenarios {
|
for _, s := range scenarios {
|
||||||
str, err := RenderList(s.input, s.isFocused)
|
str, err := RenderList(s.input, s.options...)
|
||||||
assert.EqualValues(t, s.expectedString, str)
|
assert.EqualValues(t, s.expectedString, str)
|
||||||
if s.expectedErrorMessage != "" {
|
if s.expectedErrorMessage != "" {
|
||||||
assert.EqualError(t, err, s.expectedErrorMessage)
|
assert.EqualError(t, err, s.expectedErrorMessage)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue