func (ls *Lists) String() string {
	return ls.Format()
}
String returns formatted string
package show
import (
	"bytes"
	"os"
	"github.com/gookit/color"
	"github.com/gookit/goutil/strutil"
)
type ListOption struct {
	IgnoreEmpty bool
	UpperFirst  bool
	SepChar     string  
	LeftIndent  string
	KeyWidth    int  
	KeyMinWidth int
	KeyStyle    string
	ValueStyle  string
	TitleStyle  string
}
type List struct {
	Base  
	Opts *ListOption
	title string
	data interface{}
	buffer *bytes.Buffer
}
func (l *List) SetBuffer(buffer *bytes.Buffer) {
	l.buffer = buffer
}
func NewList(title string, data interface{}) *List {
	return &List{
		title: title,
		data:  data,
		Base: Base{output: os.Stdout},
		Opts: &ListOption{
			SepChar:    " ",
			KeyStyle:   "info",
			LeftIndent: "  ",
			KeyMinWidth: 8,
			IgnoreEmpty: true,
			TitleStyle:  "comment",
		},
	}
}
func (l *List) WithOptions(fn func(opts *ListOption)) *List {
	if fn != nil {
		fn(l.Opts)
	}
	return l
}
func (l *List) Format() string {
	if l.data == nil || l.formatted != "" {
		return l.formatted
	}
	if l.buffer == nil {
		l.buffer = new(bytes.Buffer)
	}
	if l.title != "" {  
		title := strutil.UpperWord(l.title)
		l.buffer.WriteString(color.WrapTag(title, l.Opts.TitleStyle) + "\n")
	}
	items := NewItems(l.data)  
	keyWidth := items.KeyMaxWidth(l.Opts.KeyWidth)
	if keyWidth < l.Opts.KeyMinWidth {
		keyWidth = l.Opts.KeyMinWidth
	}
	for _, item := range items.List {
		if l.Opts.IgnoreEmpty && item.Val == "" {
			continue
		}
		if l.Opts.LeftIndent != "" {
			l.buffer.WriteString(l.Opts.LeftIndent)
		}
		if items.itemType == ItemMap {
			key := strutil.PadRight(item.Key, " ", keyWidth)
			key = color.WrapTag(key, l.Opts.KeyStyle)
			l.buffer.WriteString(key + l.Opts.SepChar)
		}
		val := item.Val
		if l.Opts.UpperFirst {
			val = strutil.UpperFirst(val)
		}
		l.buffer.WriteString(val + "\n")
	}
	l.formatted = l.buffer.String()
	return l.formatted
}
func (l *List) String() string {
	return l.Format()
}
func (l *List) Print() {
	l.Format()
	l.Base.Print()
}
func (l *List) Println() {
	l.Format()
	l.Base.Println()
}
func (l *List) Flush() {
	l.Println()
	l.buffer.Reset()
	l.formatted = ""
}
type Lists struct {
	Base  
	Opts *ListOption
	rows []*List
	buffer *bytes.Buffer
}
func NewLists(listMap map[string]interface{}) *Lists {
	ls := &Lists{
		Opts: &ListOption{
			SepChar:  " ",
			KeyStyle: "info",
			LeftIndent:  "  ",
			KeyMinWidth: 8,
			IgnoreEmpty: true,
			TitleStyle:  "comment",
		},
	}
	for title, data := range listMap {
		ls.rows = append(ls.rows, NewList(title, data))
	}
	return ls
}
func (ls *Lists) WithOptions(fn func(opts *ListOption)) *Lists {
	if fn != nil {
		fn(ls.Opts)
	}
	return ls
}
func (ls *Lists) Format() string {
	if len(ls.rows) == 0 || ls.formatted != "" {
		return ls.formatted
	}
	ls.buffer = new(bytes.Buffer)
	for _, list := range ls.rows {
		list.Opts = ls.Opts
		list.SetBuffer(ls.buffer)
		list.Format()
	}
	ls.formatted = ls.buffer.String()
	return ls.formatted
}