console.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. package console
  2. import (
  3. "bytes"
  4. "fmt"
  5. "strings"
  6. "unicode/utf8"
  7. )
  8. type Options struct {
  9. Bordered bool
  10. Header bool
  11. }
  12. func printBorder(w *bytes.Buffer, ws []int) {
  13. for _, l := range ws {
  14. w.WriteString("+")
  15. w.WriteString(strings.Repeat("-", l+2))
  16. }
  17. w.WriteString("+\n")
  18. }
  19. func calcCharsetWidth(s string) int {
  20. bl := len(s)
  21. ul := utf8.RuneCountInString(s)
  22. if bl == ul {
  23. return bl
  24. } else {
  25. var wc int
  26. //计算中文词语数量,并且替换为2个长度显示
  27. for wc = ((bl - ul) / 3); wc < ul; wc++ {
  28. if wc*3-wc == bl-ul {
  29. break
  30. }
  31. }
  32. wv := wc*2 + (ul - wc)
  33. return wv
  34. }
  35. }
  36. func Pretty(values [][]interface{}, opts *Options) []byte {
  37. columns := make([][]string, 0)
  38. var widths []int
  39. var width int
  40. var maxLength int
  41. if opts == nil {
  42. opts = &Options{}
  43. }
  44. calcWidth := calcCharsetWidth
  45. for _, value := range values {
  46. if len(value) > maxLength {
  47. maxLength = len(value)
  48. }
  49. }
  50. widths = make([]int, maxLength)
  51. for _, vs := range values {
  52. vl := len(vs)
  53. column := make([]string, vl)
  54. for i, val := range vs {
  55. str := fmt.Sprint(val)
  56. if vl > 1 {
  57. width = calcWidth(str)
  58. if width > widths[i] {
  59. widths[i] = width
  60. }
  61. }
  62. column[i] = str
  63. }
  64. columns = append(columns, column)
  65. }
  66. buffer := &bytes.Buffer{}
  67. if opts.Bordered {
  68. printBorder(buffer, widths)
  69. }
  70. for index, column := range columns {
  71. cl := len(column)
  72. for i, w := range widths {
  73. if opts.Bordered {
  74. buffer.WriteString("|")
  75. }
  76. var str string
  77. if cl > i {
  78. str = column[i]
  79. }
  80. if opts.Bordered {
  81. buffer.WriteString(" ")
  82. }
  83. buffer.WriteString(str)
  84. cl := calcWidth(str)
  85. if widths[i] >= cl {
  86. buffer.WriteString(strings.Repeat(" ", w-cl))
  87. }
  88. buffer.WriteString(" ")
  89. //key value options
  90. if len(widths) == 2 && i == 0 && len(column) == 2 && !opts.Bordered && !opts.Header {
  91. buffer.WriteString("\t")
  92. }
  93. }
  94. if opts.Bordered {
  95. buffer.WriteString("|\n")
  96. } else {
  97. buffer.WriteString("\n")
  98. }
  99. if opts.Header && index == 0 {
  100. printBorder(buffer, widths)
  101. }
  102. }
  103. if opts.Bordered {
  104. printBorder(buffer, widths)
  105. }
  106. return buffer.Bytes()
  107. }