consul/vendor/github.com/ryanuber/columnize/columnize.go

135 lines
3.3 KiB
Go

package columnize
import (
"fmt"
"strings"
)
type Config struct {
// The string by which the lines of input will be split.
Delim string
// The string by which columns of output will be separated.
Glue string
// The string by which columns of output will be prefixed.
Prefix string
// A replacement string to replace empty fields
Empty string
}
// Returns a Config with default values.
func DefaultConfig() *Config {
return &Config{
Delim: "|",
Glue: " ",
Prefix: "",
}
}
// Returns a list of elements, each representing a single item which will
// belong to a column of output.
func getElementsFromLine(config *Config, line string) []interface{} {
elements := make([]interface{}, 0)
for _, field := range strings.Split(line, config.Delim) {
value := strings.TrimSpace(field)
if value == "" && config.Empty != "" {
value = config.Empty
}
elements = append(elements, value)
}
return elements
}
// Examines a list of strings and determines how wide each column should be
// considering all of the elements that need to be printed within it.
func getWidthsFromLines(config *Config, lines []string) []int {
var widths []int
for _, line := range lines {
elems := getElementsFromLine(config, line)
for i := 0; i < len(elems); i++ {
l := len(elems[i].(string))
if len(widths) <= i {
widths = append(widths, l)
} else if widths[i] < l {
widths[i] = l
}
}
}
return widths
}
// Given a set of column widths and the number of columns in the current line,
// returns a sprintf-style format string which can be used to print output
// aligned properly with other lines using the same widths set.
func (c *Config) getStringFormat(widths []int, columns int) string {
// Start with the prefix, if any was given.
stringfmt := c.Prefix
// Create the format string from the discovered widths
for i := 0; i < columns && i < len(widths); i++ {
if i == columns-1 {
stringfmt += "%s\n"
} else {
stringfmt += fmt.Sprintf("%%-%ds%s", widths[i], c.Glue)
}
}
return stringfmt
}
// MergeConfig merges two config objects together and returns the resulting
// configuration. Values from the right take precedence over the left side.
func MergeConfig(a, b *Config) *Config {
var result Config = *a
// Return quickly if either side was nil
if a == nil || b == nil {
return &result
}
if b.Delim != "" {
result.Delim = b.Delim
}
if b.Glue != "" {
result.Glue = b.Glue
}
if b.Prefix != "" {
result.Prefix = b.Prefix
}
if b.Empty != "" {
result.Empty = b.Empty
}
return &result
}
// Format is the public-facing interface that takes either a plain string
// or a list of strings and returns nicely aligned output.
func Format(lines []string, config *Config) string {
var result string
conf := MergeConfig(DefaultConfig(), config)
widths := getWidthsFromLines(conf, lines)
// Create the formatted output using the format string
for _, line := range lines {
elems := getElementsFromLine(conf, line)
stringfmt := conf.getStringFormat(widths, len(elems))
result += fmt.Sprintf(stringfmt, elems...)
}
// Remove trailing newline without removing leading/trailing space
if n := len(result); n > 0 && result[n-1] == '\n' {
result = result[:n-1]
}
return result
}
// Convenience function for using Columnize as easy as possible.
func SimpleFormat(lines []string) string {
return Format(lines, nil)
}