You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

223 lines
3.7 KiB

  1. package readline
  2. import (
  3. "bytes"
  4. "unicode"
  5. "unicode/utf8"
  6. )
  7. var runes = Runes{}
  8. var TabWidth = 4
  9. type Runes struct{}
  10. func (Runes) EqualRune(a, b rune, fold bool) bool {
  11. if a == b {
  12. return true
  13. }
  14. if !fold {
  15. return false
  16. }
  17. if a > b {
  18. a, b = b, a
  19. }
  20. if b < utf8.RuneSelf && 'A' <= a && a <= 'Z' {
  21. if b == a+'a'-'A' {
  22. return true
  23. }
  24. }
  25. return false
  26. }
  27. func (r Runes) EqualRuneFold(a, b rune) bool {
  28. return r.EqualRune(a, b, true)
  29. }
  30. func (r Runes) EqualFold(a, b []rune) bool {
  31. if len(a) != len(b) {
  32. return false
  33. }
  34. for i := 0; i < len(a); i++ {
  35. if r.EqualRuneFold(a[i], b[i]) {
  36. continue
  37. }
  38. return false
  39. }
  40. return true
  41. }
  42. func (Runes) Equal(a, b []rune) bool {
  43. if len(a) != len(b) {
  44. return false
  45. }
  46. for i := 0; i < len(a); i++ {
  47. if a[i] != b[i] {
  48. return false
  49. }
  50. }
  51. return true
  52. }
  53. func (rs Runes) IndexAllBckEx(r, sub []rune, fold bool) int {
  54. for i := len(r) - len(sub); i >= 0; i-- {
  55. found := true
  56. for j := 0; j < len(sub); j++ {
  57. if !rs.EqualRune(r[i+j], sub[j], fold) {
  58. found = false
  59. break
  60. }
  61. }
  62. if found {
  63. return i
  64. }
  65. }
  66. return -1
  67. }
  68. // Search in runes from end to front
  69. func (rs Runes) IndexAllBck(r, sub []rune) int {
  70. return rs.IndexAllBckEx(r, sub, false)
  71. }
  72. // Search in runes from front to end
  73. func (rs Runes) IndexAll(r, sub []rune) int {
  74. return rs.IndexAllEx(r, sub, false)
  75. }
  76. func (rs Runes) IndexAllEx(r, sub []rune, fold bool) int {
  77. for i := 0; i < len(r); i++ {
  78. found := true
  79. if len(r[i:]) < len(sub) {
  80. return -1
  81. }
  82. for j := 0; j < len(sub); j++ {
  83. if !rs.EqualRune(r[i+j], sub[j], fold) {
  84. found = false
  85. break
  86. }
  87. }
  88. if found {
  89. return i
  90. }
  91. }
  92. return -1
  93. }
  94. func (Runes) Index(r rune, rs []rune) int {
  95. for i := 0; i < len(rs); i++ {
  96. if rs[i] == r {
  97. return i
  98. }
  99. }
  100. return -1
  101. }
  102. func (Runes) ColorFilter(r []rune) []rune {
  103. newr := make([]rune, 0, len(r))
  104. for pos := 0; pos < len(r); pos++ {
  105. if r[pos] == '\033' && r[pos+1] == '[' {
  106. idx := runes.Index('m', r[pos+2:])
  107. if idx == -1 {
  108. continue
  109. }
  110. pos += idx + 2
  111. continue
  112. }
  113. newr = append(newr, r[pos])
  114. }
  115. return newr
  116. }
  117. var zeroWidth = []*unicode.RangeTable{
  118. unicode.Mn,
  119. unicode.Me,
  120. unicode.Cc,
  121. unicode.Cf,
  122. }
  123. var doubleWidth = []*unicode.RangeTable{
  124. unicode.Han,
  125. unicode.Hangul,
  126. unicode.Hiragana,
  127. unicode.Katakana,
  128. }
  129. func (Runes) Width(r rune) int {
  130. if r == '\t' {
  131. return TabWidth
  132. }
  133. if unicode.IsOneOf(zeroWidth, r) {
  134. return 0
  135. }
  136. if unicode.IsOneOf(doubleWidth, r) {
  137. return 2
  138. }
  139. return 1
  140. }
  141. func (Runes) WidthAll(r []rune) (length int) {
  142. for i := 0; i < len(r); i++ {
  143. length += runes.Width(r[i])
  144. }
  145. return
  146. }
  147. func (Runes) Backspace(r []rune) []byte {
  148. return bytes.Repeat([]byte{'\b'}, runes.WidthAll(r))
  149. }
  150. func (Runes) Copy(r []rune) []rune {
  151. n := make([]rune, len(r))
  152. copy(n, r)
  153. return n
  154. }
  155. func (Runes) HasPrefixFold(r, prefix []rune) bool {
  156. if len(r) < len(prefix) {
  157. return false
  158. }
  159. return runes.EqualFold(r[:len(prefix)], prefix)
  160. }
  161. func (Runes) HasPrefix(r, prefix []rune) bool {
  162. if len(r) < len(prefix) {
  163. return false
  164. }
  165. return runes.Equal(r[:len(prefix)], prefix)
  166. }
  167. func (Runes) Aggregate(candicate [][]rune) (same []rune, size int) {
  168. for i := 0; i < len(candicate[0]); i++ {
  169. for j := 0; j < len(candicate)-1; j++ {
  170. if i >= len(candicate[j]) || i >= len(candicate[j+1]) {
  171. goto aggregate
  172. }
  173. if candicate[j][i] != candicate[j+1][i] {
  174. goto aggregate
  175. }
  176. }
  177. size = i + 1
  178. }
  179. aggregate:
  180. if size > 0 {
  181. same = runes.Copy(candicate[0][:size])
  182. for i := 0; i < len(candicate); i++ {
  183. n := runes.Copy(candicate[i])
  184. copy(n, n[size:])
  185. candicate[i] = n[:len(n)-size]
  186. }
  187. }
  188. return
  189. }
  190. func (Runes) TrimSpaceLeft(in []rune) []rune {
  191. firstIndex := len(in)
  192. for i, r := range in {
  193. if unicode.IsSpace(r) == false {
  194. firstIndex = i
  195. break
  196. }
  197. }
  198. return in[firstIndex:]
  199. }