123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- package console
- import (
- "bytes"
- "fmt"
- "strings"
- "unicode/utf8"
- )
- type Table [][]interface{}
- type Options struct {
- Bordered bool
- Header bool
- }
- func printBorder(w *bytes.Buffer, ws []int) {
- for _, l := range ws {
- w.WriteString("+")
- w.WriteString(strings.Repeat("-", l+2))
- }
- w.WriteString("+\n")
- }
- func calcCharsetWidth(s string) int {
- bl := len(s)
- ul := utf8.RuneCountInString(s)
- if bl == ul {
- return bl
- } else {
- var wc int
- //计算中文词语数量,并且替换为2个长度显示
- for wc = ((bl - ul) / 3); wc < ul; wc++ {
- if wc*3-wc == bl-ul {
- break
- }
- }
- wv := wc*2 + (ul - wc)
- return wv
- }
- }
- func Pretty(values Table, opts *Options) []byte {
- columns := make([][]string, 0)
- var widths []int
- var width int
- var maxLength int
- if opts == nil {
- opts = &Options{}
- }
- calcWidth := calcCharsetWidth
- for _, value := range values {
- if len(value) > maxLength {
- maxLength = len(value)
- }
- }
- widths = make([]int, maxLength)
- for _, vs := range values {
- vl := len(vs)
- column := make([]string, vl)
- for i, val := range vs {
- str := fmt.Sprint(val)
- if vl > 1 {
- width = calcWidth(str)
- if width > widths[i] {
- widths[i] = width
- }
- }
- column[i] = str
- }
- columns = append(columns, column)
- }
- buffer := &bytes.Buffer{}
- if opts.Bordered {
- printBorder(buffer, widths)
- }
- for index, column := range columns {
- cl := len(column)
- for i, w := range widths {
- if opts.Bordered {
- buffer.WriteString("|")
- }
- var str string
- if cl > i {
- str = column[i]
- }
- if opts.Bordered {
- buffer.WriteString(" ")
- }
- buffer.WriteString(str)
- cl := calcWidth(str)
- if widths[i] >= cl {
- buffer.WriteString(strings.Repeat(" ", w-cl))
- }
- buffer.WriteString(" ")
- //key value options
- if len(widths) == 2 && i == 0 && len(column) == 2 && !opts.Bordered && !opts.Header {
- buffer.WriteString("\t")
- }
- }
- if opts.Bordered {
- buffer.WriteString("|\n")
- } else {
- buffer.WriteString("\n")
- }
- if opts.Header && index == 0 {
- printBorder(buffer, widths)
- }
- }
- if opts.Bordered {
- printBorder(buffer, widths)
- }
- return buffer.Bytes()
- }
|