method.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. package ansi
  2. // Method is a type that represents the how the renderer should calculate the
  3. // display width of cells.
  4. type Method uint8
  5. // Display width modes.
  6. const (
  7. WcWidth Method = iota
  8. GraphemeWidth
  9. )
  10. // StringWidth returns the width of a string in cells. This is the number of
  11. // cells that the string will occupy when printed in a terminal. ANSI escape
  12. // codes are ignored and wide characters (such as East Asians and emojis) are
  13. // accounted for.
  14. func (m Method) StringWidth(s string) int {
  15. return stringWidth(m, s)
  16. }
  17. // Truncate truncates a string to a given length, adding a tail to the end if
  18. // the string is longer than the given length. This function is aware of ANSI
  19. // escape codes and will not break them, and accounts for wide-characters (such
  20. // as East-Asian characters and emojis).
  21. func (m Method) Truncate(s string, length int, tail string) string {
  22. return truncate(m, s, length, tail)
  23. }
  24. // TruncateLeft truncates a string to a given length, adding a prefix to the
  25. // beginning if the string is longer than the given length. This function is
  26. // aware of ANSI escape codes and will not break them, and accounts for
  27. // wide-characters (such as East-Asian characters and emojis).
  28. func (m Method) TruncateLeft(s string, length int, prefix string) string {
  29. return truncateLeft(m, s, length, prefix)
  30. }
  31. // Cut the string, without adding any prefix or tail strings. This function is
  32. // aware of ANSI escape codes and will not break them, and accounts for
  33. // wide-characters (such as East-Asian characters and emojis). Note that the
  34. // [left] parameter is inclusive, while [right] isn't.
  35. func (m Method) Cut(s string, left, right int) string {
  36. return cut(m, s, left, right)
  37. }
  38. // Hardwrap wraps a string or a block of text to a given line length, breaking
  39. // word boundaries. This will preserve ANSI escape codes and will account for
  40. // wide-characters in the string.
  41. // When preserveSpace is true, spaces at the beginning of a line will be
  42. // preserved.
  43. // This treats the text as a sequence of graphemes.
  44. func (m Method) Hardwrap(s string, length int, preserveSpace bool) string {
  45. return hardwrap(m, s, length, preserveSpace)
  46. }
  47. // Wordwrap wraps a string or a block of text to a given line length, not
  48. // breaking word boundaries. This will preserve ANSI escape codes and will
  49. // account for wide-characters in the string.
  50. // The breakpoints string is a list of characters that are considered
  51. // breakpoints for word wrapping. A hyphen (-) is always considered a
  52. // breakpoint.
  53. //
  54. // Note: breakpoints must be a string of 1-cell wide rune characters.
  55. func (m Method) Wordwrap(s string, length int, breakpoints string) string {
  56. return wordwrap(m, s, length, breakpoints)
  57. }
  58. // Wrap wraps a string or a block of text to a given line length, breaking word
  59. // boundaries if necessary. This will preserve ANSI escape codes and will
  60. // account for wide-characters in the string. The breakpoints string is a list
  61. // of characters that are considered breakpoints for word wrapping. A hyphen
  62. // (-) is always considered a breakpoint.
  63. //
  64. // Note: breakpoints must be a string of 1-cell wide rune characters.
  65. func (m Method) Wrap(s string, length int, breakpoints string) string {
  66. return wrap(m, s, length, breakpoints)
  67. }
  68. // DecodeSequence decodes the first ANSI escape sequence or a printable
  69. // grapheme from the given data. It returns the sequence slice, the number of
  70. // bytes read, the cell width for each sequence, and the new state.
  71. //
  72. // The cell width will always be 0 for control and escape sequences, 1 for
  73. // ASCII printable characters, and the number of cells other Unicode characters
  74. // occupy. It uses the uniseg package to calculate the width of Unicode
  75. // graphemes and characters. This means it will always do grapheme clustering
  76. // (mode 2027).
  77. //
  78. // Passing a non-nil [*Parser] as the last argument will allow the decoder to
  79. // collect sequence parameters, data, and commands. The parser cmd will have
  80. // the packed command value that contains intermediate and prefix characters.
  81. // In the case of a OSC sequence, the cmd will be the OSC command number. Use
  82. // [Cmd] and [Param] types to unpack command intermediates and prefixes as well
  83. // as parameters.
  84. //
  85. // Zero [Cmd] means the CSI, DCS, or ESC sequence is invalid. Moreover, checking the
  86. // validity of other data sequences, OSC, DCS, etc, will require checking for
  87. // the returned sequence terminator bytes such as ST (ESC \\) and BEL).
  88. //
  89. // We store the command byte in [Cmd] in the most significant byte, the
  90. // prefix byte in the next byte, and the intermediate byte in the least
  91. // significant byte. This is done to avoid using a struct to store the command
  92. // and its intermediates and prefixes. The command byte is always the least
  93. // significant byte i.e. [Cmd & 0xff]. Use the [Cmd] type to unpack the
  94. // command, intermediate, and prefix bytes. Note that we only collect the last
  95. // prefix character and intermediate byte.
  96. //
  97. // The [p.Params] slice will contain the parameters of the sequence. Any
  98. // sub-parameter will have the [parser.HasMoreFlag] set. Use the [Param] type
  99. // to unpack the parameters.
  100. //
  101. // Example:
  102. //
  103. // var state byte // the initial state is always zero [NormalState]
  104. // p := NewParser(32, 1024) // create a new parser with a 32 params buffer and 1024 data buffer (optional)
  105. // input := []byte("\x1b[31mHello, World!\x1b[0m")
  106. // for len(input) > 0 {
  107. // seq, width, n, newState := DecodeSequence(input, state, p)
  108. // log.Printf("seq: %q, width: %d", seq, width)
  109. // state = newState
  110. // input = input[n:]
  111. // }
  112. func (m Method) DecodeSequence(data []byte, state byte, p *Parser) (seq []byte, width, n int, newState byte) {
  113. return decodeSequence(m, data, state, p)
  114. }
  115. // DecodeSequenceInString decodes the first ANSI escape sequence or a printable
  116. // grapheme from the given data. It returns the sequence slice, the number of
  117. // bytes read, the cell width for each sequence, and the new state.
  118. //
  119. // The cell width will always be 0 for control and escape sequences, 1 for
  120. // ASCII printable characters, and the number of cells other Unicode characters
  121. // occupy. It uses the uniseg package to calculate the width of Unicode
  122. // graphemes and characters. This means it will always do grapheme clustering
  123. // (mode 2027).
  124. //
  125. // Passing a non-nil [*Parser] as the last argument will allow the decoder to
  126. // collect sequence parameters, data, and commands. The parser cmd will have
  127. // the packed command value that contains intermediate and prefix characters.
  128. // In the case of a OSC sequence, the cmd will be the OSC command number. Use
  129. // [Cmd] and [Param] types to unpack command intermediates and prefixes as well
  130. // as parameters.
  131. //
  132. // Zero [Cmd] means the CSI, DCS, or ESC sequence is invalid. Moreover, checking the
  133. // validity of other data sequences, OSC, DCS, etc, will require checking for
  134. // the returned sequence terminator bytes such as ST (ESC \\) and BEL).
  135. //
  136. // We store the command byte in [Cmd] in the most significant byte, the
  137. // prefix byte in the next byte, and the intermediate byte in the least
  138. // significant byte. This is done to avoid using a struct to store the command
  139. // and its intermediates and prefixes. The command byte is always the least
  140. // significant byte i.e. [Cmd & 0xff]. Use the [Cmd] type to unpack the
  141. // command, intermediate, and prefix bytes. Note that we only collect the last
  142. // prefix character and intermediate byte.
  143. //
  144. // The [p.Params] slice will contain the parameters of the sequence. Any
  145. // sub-parameter will have the [parser.HasMoreFlag] set. Use the [Param] type
  146. // to unpack the parameters.
  147. //
  148. // Example:
  149. //
  150. // var state byte // the initial state is always zero [NormalState]
  151. // p := NewParser(32, 1024) // create a new parser with a 32 params buffer and 1024 data buffer (optional)
  152. // input := []byte("\x1b[31mHello, World!\x1b[0m")
  153. // for len(input) > 0 {
  154. // seq, width, n, newState := DecodeSequenceInString(input, state, p)
  155. // log.Printf("seq: %q, width: %d", seq, width)
  156. // state = newState
  157. // input = input[n:]
  158. // }
  159. func (m Method) DecodeSequenceInString(data string, state byte, p *Parser) (seq string, width, n int, newState byte) {
  160. return decodeSequence(m, data, state, p)
  161. }