screen.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. package terminalparser
  2. import (
  3. "bytes"
  4. "log"
  5. "strconv"
  6. "unicode/utf8"
  7. "github.com/mattn/go-runewidth"
  8. )
  9. type Screen struct {
  10. Rows []*Row
  11. Cursor *Cursor
  12. pasteMode bool // Set bracketed paste mode, xterm. ?2004h reset ?2004l
  13. title string
  14. }
  15. func (s *Screen) Parse(data []byte) []string {
  16. s.Cursor.Y = 1
  17. s.Rows = append(s.Rows, &Row{
  18. dataRune: make([]rune, 0, 1024),
  19. })
  20. rest := data
  21. for len(rest) > 0 {
  22. code, size := utf8.DecodeRune(rest)
  23. rest = rest[size:]
  24. switch code {
  25. case ESCKey:
  26. code, size = utf8.DecodeRune(rest)
  27. rest = rest[size:]
  28. switch code {
  29. case '[':
  30. // CSI
  31. rest = s.parseCSISequence(rest)
  32. continue
  33. case ']':
  34. // OSC
  35. rest = s.parseOSCSequence(rest)
  36. continue
  37. default:
  38. if existIndex := bytes.IndexRune([]byte(string(Intermediate)), code); existIndex >= 0 {
  39. // ESC
  40. rest = s.parseIntermediate(code, rest)
  41. continue
  42. }
  43. if existIndex := bytes.IndexRune([]byte(string(Parameters)), code); existIndex >= 0 {
  44. log.Printf("Screen 未解析 ESC `%q` %xParameters字符\n", code, code)
  45. continue
  46. }
  47. if existIndex := bytes.IndexRune([]byte(string(Uppercase)), code); existIndex >= 0 {
  48. log.Printf("Screen 未解析 ESC `%q` %x Uppercase字符\n", code, code)
  49. continue
  50. }
  51. if existIndex := bytes.IndexRune([]byte(string(Lowercase)), code); existIndex >= 0 {
  52. log.Printf("Screen 未解析 ESC `%q` %x Lowercase字符\n", code, code)
  53. continue
  54. }
  55. log.Printf("Screen 未解析 ESC `%q` %x\n", code, code)
  56. }
  57. continue
  58. case Delete:
  59. continue
  60. default:
  61. if existIndex := bytes.IndexRune([]byte(string(C0Control)), code); existIndex >= 0 {
  62. s.parseC0Sequence(code)
  63. } else {
  64. if len(s.Rows) == 0 && s.Cursor.Y == 0 {
  65. s.Rows = append(s.Rows, &Row{
  66. dataRune: make([]rune, 0, 1024),
  67. })
  68. s.Cursor.Y++
  69. }
  70. s.appendCharacter(code)
  71. }
  72. continue
  73. }
  74. }
  75. result := make([]string, len(s.Rows))
  76. for i := range s.Rows {
  77. result[i] = s.Rows[i].String()
  78. }
  79. return result
  80. }
  81. func (s *Screen) parseC0Sequence(code rune) {
  82. switch code {
  83. case 0x07:
  84. //bell 忽略
  85. case 0x08:
  86. // 后退1光标
  87. s.Cursor.MoveLeft(1)
  88. case 0x0d:
  89. /*
  90. \r
  91. */
  92. s.Cursor.X = 0
  93. if s.Cursor.Y > len(s.Rows) {
  94. s.Rows = append(s.Rows, &Row{
  95. dataRune: make([]rune, 0, 1024),
  96. })
  97. }
  98. case 0x0a:
  99. /*
  100. \n
  101. */
  102. s.Cursor.Y++
  103. if s.Cursor.Y > len(s.Rows) {
  104. s.Rows = append(s.Rows, &Row{
  105. dataRune: make([]rune, 0, 1024),
  106. })
  107. }
  108. default:
  109. log.Printf("未处理的字符 %q %v\n", code, code)
  110. }
  111. }
  112. func (s *Screen) parseCSISequence(p []byte) []byte {
  113. endIndex := bytes.IndexFunc(p, IsAlphabetic)
  114. params := []rune(string(p[:endIndex]))
  115. switch rune(p[endIndex]) {
  116. case 'Y':
  117. // /*
  118. // ESC Y Ps Ps
  119. // Move the cursor to given row and column.
  120. // */
  121. if len(p[endIndex+1:]) < 2 {
  122. return p[endIndex+1:]
  123. }
  124. if row, err := strconv.Atoi(string(p[endIndex+1])); err == nil {
  125. s.Cursor.Y = row
  126. }
  127. if col, err := strconv.Atoi(string(p[endIndex+2])); err == nil {
  128. s.Cursor.X = col
  129. }
  130. return p[endIndex+3:]
  131. }
  132. funcName, ok := CSIFuncMap[rune(p[endIndex])]
  133. if ok {
  134. funcName(s, params)
  135. } else {
  136. log.Printf("screen未处理的CSI %s %q\n", DebugString(string(params)), p[endIndex])
  137. }
  138. return p[endIndex+1:]
  139. }
  140. func (s *Screen) parseIntermediate(code rune, p []byte) []byte {
  141. switch code {
  142. case '(':
  143. terminationIndex := bytes.IndexFunc(p, func(r rune) bool {
  144. if insideIndex := bytes.IndexRune([]byte(string(Alphabetic)), r); insideIndex < 0 {
  145. return false
  146. }
  147. return true
  148. })
  149. params := p[:terminationIndex+1]
  150. switch string(params) {
  151. case "B":
  152. /*
  153. ESC ( C Designate G0 Character Set, VT100, ISO 2022.
  154. C = B ⇒ United States (USASCII), VT100.
  155. */
  156. }
  157. p = p[terminationIndex+1:]
  158. return p
  159. case ')':
  160. terminationIndex := bytes.IndexFunc(p, func(r rune) bool {
  161. if insideIndex := bytes.IndexRune([]byte(string(Alphabetic)), r); insideIndex < 0 {
  162. return false
  163. }
  164. return true
  165. })
  166. p = p[terminationIndex+1:]
  167. default:
  168. log.Printf("Screen 未解析 ESC `%q` %x Intermediate字符\n", code, code)
  169. }
  170. return p
  171. }
  172. func (s *Screen) parseOSCSequence(p []byte) []byte {
  173. if endIndex := bytes.IndexRune(p, BEL); endIndex >= 0 {
  174. return p[endIndex+1:]
  175. }
  176. if endIndex := bytes.IndexRune(p, ST); endIndex >= 0 {
  177. return p[endIndex+1:]
  178. }
  179. log.Println("未处理的 parseOSCSequence")
  180. return p
  181. }
  182. func (s *Screen) appendCharacter(code rune) {
  183. currentRow := s.GetCursorRow()
  184. currentRow.changeCursorToX(s.Cursor.X)
  185. currentRow.appendCharacter(code)
  186. width := runewidth.StringWidth(string(code))
  187. s.Cursor.X += width
  188. }
  189. func (s *Screen) eraseEndToLine() {
  190. currentRow := s.GetCursorRow()
  191. currentRow.changeCursorToX(s.Cursor.X)
  192. currentRow.eraseRight()
  193. }
  194. func (s *Screen) eraseRight() {
  195. currentRow := s.GetCursorRow()
  196. currentRow.changeCursorToX(s.Cursor.X)
  197. currentRow.eraseRight()
  198. }
  199. func (s *Screen) eraseLeft() {
  200. log.Printf("Screen %s Erase Left cursor(%d,%d) 总Row数量 %d",
  201. UnsupportedMsg, s.Cursor.X, s.Cursor.Y, len(s.Rows))
  202. }
  203. func (s *Screen) eraseAbove() {
  204. s.Rows = s.Rows[s.Cursor.Y-1:]
  205. }
  206. func (s *Screen) eraseBelow() {
  207. s.Rows = s.Rows[:s.Cursor.Y]
  208. }
  209. func (s *Screen) eraseAll() {
  210. s.Rows = s.Rows[:0]
  211. //htop?
  212. s.Cursor.X = 0
  213. s.Cursor.Y = 0
  214. }
  215. func (s *Screen) eraseFromCursor() {
  216. if s.Cursor.Y > len(s.Rows) {
  217. s.Cursor.Y = len(s.Rows)
  218. }
  219. s.Rows = s.Rows[:s.Cursor.Y]
  220. currentRow := s.GetCursorRow()
  221. currentRow.changeCursorToX(s.Cursor.X)
  222. currentRow.eraseRight()
  223. }
  224. func (s *Screen) deleteChars(ps int) {
  225. currentRow := s.GetCursorRow()
  226. currentRow.changeCursorToX(s.Cursor.X)
  227. currentRow.deleteChars(ps)
  228. }
  229. func (s *Screen) GetCursorRow() *Row {
  230. if s.Cursor.Y == 0 {
  231. s.Cursor.Y++
  232. }
  233. if len(s.Rows) == 0 {
  234. s.Rows = append(s.Rows, &Row{
  235. dataRune: make([]rune, 0, 1024),
  236. })
  237. }
  238. index := s.Cursor.Y - 1
  239. if index >= len(s.Rows) {
  240. log.Printf("总行数 %d 比当前行 %d 小,可能存在解析错误 \n", len(s.Rows), s.Cursor.Y)
  241. return s.Rows[len(s.Rows)-1]
  242. }
  243. return s.Rows[s.Cursor.Y-1]
  244. }
  245. const UnsupportedMsg = "Unsupported"