func (ui *UI) DisplayKeyValueTable(prefix string, table [][]string, padding int) {
	rows := len(table)
	if rows == 0 {
		return
	}
	columns := len(table[0])
	if columns < 2 || !ui.IsTTY {
		ui.DisplayNonWrappingTable(prefix, table, padding)
		return
	}
	ui.displayWrappingTableWithWidth(prefix, table, padding)
}
DisplayKeyValueTable outputs a matrix of strings as a table to UI.Out.
Prefix will be prepended to each row and padding adds the specified number
of spaces between columns. The final columns may wrap to multiple lines but
will still be confined to the last column. Wrapping will occur on word
boundaries.
package ui
import (
	"fmt"
	"io"
	"os"
	"strings"
	"sync"
	"time"
	"code.cloudfoundry.org/cli/command/translatableerror"
	"code.cloudfoundry.org/cli/util/configv3"
	"github.com/fatih/color"
	"github.com/lunixbochs/vtclean"
	runewidth "github.com/mattn/go-runewidth"
	"github.com/vito/go-interact/interact"
)
const LogTimestampFormat = "2006-01-02T15:04:05.00-0700"
const DefaultTableSpacePadding = 3
type Config interface {
	ColorEnabled() configv3.ColorSetting
	Locale() string
	IsTTY() bool
	TerminalWidth() int
}
type LogMessage interface {
	Message() string
	Type() string
	Timestamp() time.Time
	SourceType() string
	SourceInstance() string
}
type UI struct {
	In io.Reader
	Out io.Writer
	OutForInteration io.Writer
	Err io.Writer
	colorEnabled configv3.ColorSetting
	translate    TranslateFunc
	terminalLock *sync.Mutex
	fileLock     *sync.Mutex
	IsTTY         bool
	TerminalWidth int
	TimezoneLocation *time.Location
}
func NewUI(config Config) (*UI, error) {
	translateFunc, err := GetTranslationFunc(config)
	if err != nil {
		return nil, err
	}
	location := time.Now().Location()
	return &UI{
		In:               os.Stdin,
		Out:              color.Output,
		OutForInteration: os.Stdout,
		Err:              os.Stderr,
		colorEnabled:     config.ColorEnabled(),
		translate:        translateFunc,
		terminalLock:     &sync.Mutex{},
		fileLock:         &sync.Mutex{},
		IsTTY:            config.IsTTY(),
		TerminalWidth:    config.TerminalWidth(),
		TimezoneLocation: location,
	}, nil
}
func NewTestUI(in io.Reader, out io.Writer, err io.Writer) *UI {
	translationFunc, translateErr := generateTranslationFunc([]byte("[]"))
	if translateErr != nil {
		panic(translateErr)
	}
	return &UI{
		In:               in,
		Out:              out,
		OutForInteration: out,
		Err:              err,
		colorEnabled:     configv3.ColorDisabled,
		translate:        translationFunc,
		terminalLock:     &sync.Mutex{},
		fileLock:         &sync.Mutex{},
		TimezoneLocation: time.UTC,
	}
}
func (ui *UI) GetIn() io.Reader {
	return ui.In
}
func (ui *UI) GetOut() io.Writer {
	return ui.Out
}
func (ui *UI) GetErr() io.Writer {
	return ui.Err
}
func (ui *UI) DisplayBoolPrompt(defaultResponse bool, template string, templateValues ...map[string]interface{}) (bool, error) {
	ui.terminalLock.Lock()
	defer ui.terminalLock.Unlock()
	response := defaultResponse
	interactivePrompt := interact.NewInteraction(ui.TranslateText(template, templateValues...))
	interactivePrompt.Input = ui.In
	interactivePrompt.Output = ui.OutForInteration
	err := interactivePrompt.Resolve(&response)
	return response, err
}
func (ui *UI) DisplayPasswordPrompt(template string, templateValues ...map[string]interface{}) (string, error) {
	ui.terminalLock.Lock()
	defer ui.terminalLock.Unlock()
	var password interact.Password
	interactivePrompt := interact.NewInteraction(ui.TranslateText(template, templateValues...))
	interactivePrompt.Input = ui.In
	interactivePrompt.Output = ui.OutForInteration
	err := interactivePrompt.Resolve(interact.Required(&password))
	return string(password), err
}
func (ui *UI) DisplayError(err error) {
	var errMsg string
	if translatableError, ok := err.(translatableerror.TranslatableError); ok {
		errMsg = translatableError.Translate(ui.translate)
	} else {
		errMsg = err.Error()
	}
	fmt.Fprintf(ui.Err, "%s\n", errMsg)
	ui.terminalLock.Lock()
	defer ui.terminalLock.Unlock()
	fmt.Fprintf(ui.Out, "%s\n", ui.modifyColor(ui.TranslateText("FAILED"), color.New(color.FgRed, color.Bold)))
}
func (ui *UI) DisplayHeader(text string) {
	ui.terminalLock.Lock()
	defer ui.terminalLock.Unlock()
	fmt.Fprintf(ui.Out, "%s\n", ui.modifyColor(ui.TranslateText(text), color.New(color.Bold)))
}