console.go 2.1 KB

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