print.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. package text
  2. import (
  3. "fmt"
  4. "os"
  5. "strconv"
  6. "strings"
  7. "syscall"
  8. "unicode"
  9. "github.com/leonelquinteros/gotext"
  10. "golang.org/x/sys/unix"
  11. )
  12. const (
  13. arrow = "==>"
  14. smallArrow = " ->"
  15. opSymbol = "::"
  16. )
  17. var (
  18. cachedColumnCount = -1
  19. DebugMode = false
  20. globalLogger = NewLogger(os.Stdout, os.Stdin, DebugMode, "global")
  21. )
  22. func Debugln(a ...interface{}) {
  23. globalLogger.Debugln(a...)
  24. }
  25. func OperationInfoln(a ...interface{}) {
  26. globalLogger.OperationInfoln(a...)
  27. }
  28. func OperationInfo(a ...interface{}) {
  29. globalLogger.OperationInfo(a...)
  30. }
  31. func SprintOperationInfo(a ...interface{}) string {
  32. return globalLogger.SprintOperationInfo(a...)
  33. }
  34. func Info(a ...interface{}) {
  35. globalLogger.Info(a...)
  36. }
  37. func Infoln(a ...interface{}) {
  38. globalLogger.Infoln(a...)
  39. }
  40. func SprintWarn(a ...interface{}) string {
  41. return globalLogger.SprintWarn(a...)
  42. }
  43. func Warn(a ...interface{}) {
  44. globalLogger.Warn(a...)
  45. }
  46. func Warnln(a ...interface{}) {
  47. globalLogger.Warnln(a...)
  48. }
  49. func SprintError(a ...interface{}) string {
  50. return globalLogger.SprintError(a...)
  51. }
  52. func Error(a ...interface{}) {
  53. globalLogger.Error(a...)
  54. }
  55. func Errorln(a ...interface{}) {
  56. globalLogger.Errorln(a...)
  57. }
  58. func getColumnCount() int {
  59. if cachedColumnCount > 0 {
  60. return cachedColumnCount
  61. }
  62. if count, err := strconv.Atoi(os.Getenv("COLUMNS")); err == nil {
  63. cachedColumnCount = count
  64. return cachedColumnCount
  65. }
  66. if ws, err := unix.IoctlGetWinsize(syscall.Stdout, unix.TIOCGWINSZ); err == nil {
  67. cachedColumnCount = int(ws.Col)
  68. return cachedColumnCount
  69. }
  70. return 80
  71. }
  72. func PrintInfoValue(key string, values ...string) {
  73. const (
  74. keyLength = 32
  75. delimCount = 2
  76. )
  77. specialWordsCount := 0
  78. for _, runeValue := range key {
  79. // CJK handling: the character 'ー' is Katakana
  80. // but if use unicode.Katakana, it will return false
  81. if unicode.IsOneOf([]*unicode.RangeTable{
  82. unicode.Han,
  83. unicode.Hiragana,
  84. unicode.Katakana,
  85. unicode.Hangul,
  86. }, runeValue) || runeValue == 'ー' {
  87. specialWordsCount++
  88. }
  89. }
  90. keyTextCount := specialWordsCount - keyLength + delimCount
  91. str := fmt.Sprintf(Bold("%-*s: "), keyTextCount, key)
  92. if len(values) == 0 || (len(values) == 1 && values[0] == "") {
  93. fmt.Fprintf(os.Stdout, "%s%s\n", str, gotext.Get("None"))
  94. return
  95. }
  96. maxCols := getColumnCount()
  97. cols := keyLength + len(values[0])
  98. str += values[0]
  99. for _, value := range values[1:] {
  100. if maxCols > keyLength && cols+len(value)+delimCount >= maxCols {
  101. cols = keyLength
  102. str += "\n" + strings.Repeat(" ", keyLength)
  103. } else if cols != keyLength {
  104. str += strings.Repeat(" ", delimCount)
  105. cols += delimCount
  106. }
  107. str += value
  108. cols += len(value)
  109. }
  110. fmt.Println(str)
  111. }