line.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. package door
  2. import (
  3. "fmt"
  4. "strings"
  5. "unicode"
  6. )
  7. type Line struct {
  8. Text string
  9. DefaultColor string
  10. RenderF func(string) string
  11. UpdateF func() string
  12. }
  13. func (l *Line) Update() bool {
  14. if l.UpdateF == nil {
  15. return false
  16. }
  17. NewText := l.UpdateF()
  18. if NewText != l.Text {
  19. l.Text = NewText
  20. return true
  21. }
  22. return false
  23. }
  24. func (l *Line) Output() string {
  25. if l.RenderF == nil {
  26. return l.DefaultColor + l.Text
  27. } else {
  28. return l.RenderF(l.Text)
  29. }
  30. }
  31. // Sample RenderF function
  32. // Upcase is BOLD Blue, everything else is Yellow
  33. func RenderBlueYellow(text string) string {
  34. var output string
  35. var lastColor string
  36. blue := ColorText("BOLD BLUE")
  37. yellow := ColorText("BOLD YELLOW")
  38. for _, letter := range text {
  39. if unicode.IsUpper(letter) {
  40. if lastColor != blue {
  41. lastColor = blue
  42. output += blue
  43. }
  44. output += string(letter)
  45. } else {
  46. if lastColor != yellow {
  47. lastColor = yellow
  48. output += yellow
  49. }
  50. output += string(letter)
  51. }
  52. }
  53. return output
  54. }
  55. type BarStyle int
  56. const (
  57. SOLID BarStyle = iota
  58. HALF_STEP
  59. GRADIENT
  60. PERCENTAGE
  61. PERCENT_SPACE
  62. )
  63. type BarRange struct {
  64. Percent int64
  65. Color string
  66. }
  67. type BarLine struct {
  68. Width int
  69. Style BarStyle
  70. Percent int64 // percentage * 100
  71. ColorRange []BarRange
  72. UpdateP func() int64
  73. Line
  74. }
  75. func (bl *BarLine) CheckRange() {
  76. if len(bl.ColorRange) != 0 {
  77. // Ok, there is a color range. Get checking
  78. for _, br := range bl.ColorRange {
  79. if bl.Percent <= br.Percent {
  80. bl.DefaultColor = br.Color
  81. break
  82. }
  83. }
  84. }
  85. }
  86. func (bl *BarLine) Output() string {
  87. var output string
  88. var step_width int64
  89. if bl.UpdateP != nil {
  90. bl.Percent = bl.UpdateP()
  91. }
  92. bl.CheckRange()
  93. switch bl.Style {
  94. case SOLID, PERCENTAGE, PERCENT_SPACE:
  95. step_width = int64(100 * 100 / bl.Width)
  96. var steps int = int(bl.Percent / step_width)
  97. if Unicode {
  98. output += strings.Repeat("\u2588", steps)
  99. } else {
  100. output += strings.Repeat("\xdb", steps)
  101. }
  102. // This will work, because we aren't trying to len(output) with unicode.
  103. output += strings.Repeat(" ", int(bl.Width-steps))
  104. if bl.Style == PERCENTAGE || bl.Style == PERCENT_SPACE {
  105. percent := fmt.Sprintf("%d", bl.Percent/100)
  106. var pos int = bl.Width/2 - 1
  107. if percent != "100" {
  108. percent += "%"
  109. if len(percent) < 3 {
  110. percent = " " + percent
  111. }
  112. }
  113. if bl.Style == PERCENT_SPACE {
  114. percent = " " + percent + " "
  115. pos--
  116. }
  117. // to process/slice the string (with unicode) do this:
  118. // convert to []rune, slice that, convert back to string
  119. //
  120. // sliceable := []rune(output)
  121. // newString := string(sliceable[:5]) + " new content " + (sliceable[10:])
  122. // fmt.Printf("%d %d [%s] %d [%s]\n", bl.Width, pos, percent, len(output), output)
  123. if Unicode {
  124. runes := []rune(output)
  125. output = string(runes[:pos]) + percent + string(runes[pos+len(percent):])
  126. } else {
  127. output = output[:pos] + percent + output[pos+len(percent):]
  128. }
  129. }
  130. case HALF_STEP:
  131. step_width = int64(100 * 100 / bl.Width)
  132. var steps int = int(bl.Percent * 2 / step_width)
  133. if Unicode {
  134. output += strings.Repeat("\u2588", steps/2)
  135. } else {
  136. output += strings.Repeat("\xdb", steps/2)
  137. }
  138. if steps%1 == 1 {
  139. if Unicode {
  140. output += "\u258c"
  141. } else {
  142. output += "\xdd"
  143. }
  144. steps++
  145. }
  146. output += strings.Repeat(" ", bl.Width-(steps/2))
  147. case GRADIENT:
  148. step_width = int64(100 * 100 / bl.Width)
  149. var steps int = int(bl.Percent * 4 / step_width)
  150. if Unicode {
  151. output += strings.Repeat("\u2588", steps/4)
  152. } else {
  153. output += strings.Repeat("\xb0", steps/4)
  154. }
  155. if steps%4 != 0 {
  156. switch steps % 4 {
  157. case 1:
  158. if Unicode {
  159. output += "\u2591"
  160. } else {
  161. output += "\xb0"
  162. }
  163. case 2:
  164. if Unicode {
  165. output += "\u2592"
  166. } else {
  167. output += "\xb1"
  168. }
  169. case 3:
  170. if Unicode {
  171. output += "\u2593"
  172. } else {
  173. output += "\xb2"
  174. }
  175. }
  176. for steps%4 != 0 {
  177. steps++
  178. }
  179. }
  180. output += strings.Repeat(" ", bl.Width-(steps/4))
  181. }
  182. return bl.DefaultColor + output
  183. }