row.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. package terminalparser
  2. import (
  3. "strings"
  4. "github.com/mattn/go-runewidth"
  5. )
  6. type Row struct {
  7. dataRune []rune
  8. currentX int
  9. currentRuneIndex int
  10. // fish shell 补全提示
  11. tipRune []rune
  12. tipRecord bool
  13. }
  14. func (r *Row) String() string {
  15. return strings.TrimSuffix(string(r.dataRune), string(r.tipRune))
  16. }
  17. func (r *Row) appendCharacter(code rune) {
  18. width := runewidth.StringWidth(string(code))
  19. if r.currentRuneIndex < len(r.dataRune) {
  20. r.dataRune[r.currentRuneIndex] = code
  21. } else {
  22. r.dataRune = append(r.dataRune, code)
  23. }
  24. r.currentRuneIndex++
  25. r.currentX += width
  26. r.addTipRune(code)
  27. }
  28. func (r *Row) insertCharacters(data []rune) {
  29. result := make([]rune, len(r.dataRune)+len(data))
  30. copy(result, r.dataRune[:r.currentRuneIndex])
  31. copy(result[r.currentRuneIndex:], data)
  32. copy(result[r.currentRuneIndex+len(data):], r.dataRune[r.currentRuneIndex:])
  33. for i := range data {
  34. r.currentRuneIndex++
  35. r.currentX += runewidth.StringWidth(string(data[i]))
  36. }
  37. r.dataRune = result
  38. }
  39. func (r *Row) eraseRight() {
  40. r.dataRune = r.dataRune[:r.currentRuneIndex]
  41. }
  42. func (r *Row) deleteChars(ps int) {
  43. result := make([]rune, r.currentRuneIndex, len(r.dataRune))
  44. copy(result, r.dataRune[:r.currentRuneIndex])
  45. rest := r.dataRune[r.currentRuneIndex:]
  46. inits := ps
  47. for i := range rest {
  48. inits -= runewidth.StringWidth(string(rest[i]))
  49. if inits == 0 {
  50. result = append(result, rest[i+1:]...)
  51. break
  52. }
  53. }
  54. r.dataRune = result
  55. }
  56. func (r *Row) changeCurrentRuneIndex() {
  57. if r.currentX < 0 {
  58. r.currentX = 0
  59. }
  60. currentRuneIndex := 0
  61. for i := range r.dataRune {
  62. currentRuneIndex += runewidth.StringWidth(string(r.dataRune[i]))
  63. if currentRuneIndex > r.currentX {
  64. r.currentRuneIndex = i
  65. return
  66. }
  67. }
  68. r.currentRuneIndex = len(r.dataRune)
  69. }
  70. func (r *Row) changeCursorToX(x int) {
  71. if r.currentX == x {
  72. return
  73. }
  74. r.currentX = x
  75. r.changeCurrentRuneIndex()
  76. }
  77. func (r *Row) startRecord() {
  78. r.tipRecord = true
  79. r.tipRune = make([]rune, 0, 100)
  80. }
  81. func (r *Row) stopRecord() {
  82. if !r.tipRecord {
  83. r.tipRune = make([]rune, 0, 100)
  84. }
  85. r.tipRecord = false
  86. }
  87. func (r *Row) addTipRune(code rune) {
  88. if r.tipRecord {
  89. r.tipRune = append(r.tipRune, code)
  90. }
  91. }