forked from toolshed/abra
		
	We were running behind and there were quite some deprecations to update. This was mostly in the upstream copy/pasta package but seems quite minimal.
		
			
				
	
	
		
			173 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			173 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package ansi
 | |
| 
 | |
| // Method is a type that represents the how the renderer should calculate the
 | |
| // display width of cells.
 | |
| type Method uint8
 | |
| 
 | |
| // Display width modes.
 | |
| const (
 | |
| 	WcWidth Method = iota
 | |
| 	GraphemeWidth
 | |
| )
 | |
| 
 | |
| // StringWidth returns the width of a string in cells. This is the number of
 | |
| // cells that the string will occupy when printed in a terminal. ANSI escape
 | |
| // codes are ignored and wide characters (such as East Asians and emojis) are
 | |
| // accounted for.
 | |
| func (m Method) StringWidth(s string) int {
 | |
| 	return stringWidth(m, s)
 | |
| }
 | |
| 
 | |
| // Truncate truncates a string to a given length, adding a tail to the end if
 | |
| // the string is longer than the given length. This function is aware of ANSI
 | |
| // escape codes and will not break them, and accounts for wide-characters (such
 | |
| // as East-Asian characters and emojis).
 | |
| func (m Method) Truncate(s string, length int, tail string) string {
 | |
| 	return truncate(m, s, length, tail)
 | |
| }
 | |
| 
 | |
| // TruncateLeft truncates a string to a given length, adding a prefix to the
 | |
| // beginning if the string is longer than the given length. This function is
 | |
| // aware of ANSI escape codes and will not break them, and accounts for
 | |
| // wide-characters (such as East-Asian characters and emojis).
 | |
| func (m Method) TruncateLeft(s string, length int, prefix string) string {
 | |
| 	return truncateLeft(m, s, length, prefix)
 | |
| }
 | |
| 
 | |
| // Cut the string, without adding any prefix or tail strings. This function is
 | |
| // aware of ANSI escape codes and will not break them, and accounts for
 | |
| // wide-characters (such as East-Asian characters and emojis). Note that the
 | |
| // [left] parameter is inclusive, while [right] isn't.
 | |
| func (m Method) Cut(s string, left, right int) string {
 | |
| 	return cut(m, s, left, right)
 | |
| }
 | |
| 
 | |
| // Hardwrap wraps a string or a block of text to a given line length, breaking
 | |
| // word boundaries. This will preserve ANSI escape codes and will account for
 | |
| // wide-characters in the string.
 | |
| // When preserveSpace is true, spaces at the beginning of a line will be
 | |
| // preserved.
 | |
| // This treats the text as a sequence of graphemes.
 | |
| func (m Method) Hardwrap(s string, length int, preserveSpace bool) string {
 | |
| 	return hardwrap(m, s, length, preserveSpace)
 | |
| }
 | |
| 
 | |
| // Wordwrap wraps a string or a block of text to a given line length, not
 | |
| // breaking word boundaries. This will preserve ANSI escape codes and will
 | |
| // account for wide-characters in the string.
 | |
| // The breakpoints string is a list of characters that are considered
 | |
| // breakpoints for word wrapping. A hyphen (-) is always considered a
 | |
| // breakpoint.
 | |
| //
 | |
| // Note: breakpoints must be a string of 1-cell wide rune characters.
 | |
| func (m Method) Wordwrap(s string, length int, breakpoints string) string {
 | |
| 	return wordwrap(m, s, length, breakpoints)
 | |
| }
 | |
| 
 | |
| // Wrap wraps a string or a block of text to a given line length, breaking word
 | |
| // boundaries if necessary. This will preserve ANSI escape codes and will
 | |
| // account for wide-characters in the string. The breakpoints string is a list
 | |
| // of characters that are considered breakpoints for word wrapping. A hyphen
 | |
| // (-) is always considered a breakpoint.
 | |
| //
 | |
| // Note: breakpoints must be a string of 1-cell wide rune characters.
 | |
| func (m Method) Wrap(s string, length int, breakpoints string) string {
 | |
| 	return wrap(m, s, length, breakpoints)
 | |
| }
 | |
| 
 | |
| // DecodeSequence decodes the first ANSI escape sequence or a printable
 | |
| // grapheme from the given data. It returns the sequence slice, the number of
 | |
| // bytes read, the cell width for each sequence, and the new state.
 | |
| //
 | |
| // The cell width will always be 0 for control and escape sequences, 1 for
 | |
| // ASCII printable characters, and the number of cells other Unicode characters
 | |
| // occupy. It uses the uniseg package to calculate the width of Unicode
 | |
| // graphemes and characters. This means it will always do grapheme clustering
 | |
| // (mode 2027).
 | |
| //
 | |
| // Passing a non-nil [*Parser] as the last argument will allow the decoder to
 | |
| // collect sequence parameters, data, and commands. The parser cmd will have
 | |
| // the packed command value that contains intermediate and prefix characters.
 | |
| // In the case of a OSC sequence, the cmd will be the OSC command number. Use
 | |
| // [Cmd] and [Param] types to unpack command intermediates and prefixes as well
 | |
| // as parameters.
 | |
| //
 | |
| // Zero [Cmd] means the CSI, DCS, or ESC sequence is invalid. Moreover, checking the
 | |
| // validity of other data sequences, OSC, DCS, etc, will require checking for
 | |
| // the returned sequence terminator bytes such as ST (ESC \\) and BEL).
 | |
| //
 | |
| // We store the command byte in [Cmd] in the most significant byte, the
 | |
| // prefix byte in the next byte, and the intermediate byte in the least
 | |
| // significant byte. This is done to avoid using a struct to store the command
 | |
| // and its intermediates and prefixes. The command byte is always the least
 | |
| // significant byte i.e. [Cmd & 0xff]. Use the [Cmd] type to unpack the
 | |
| // command, intermediate, and prefix bytes. Note that we only collect the last
 | |
| // prefix character and intermediate byte.
 | |
| //
 | |
| // The [p.Params] slice will contain the parameters of the sequence. Any
 | |
| // sub-parameter will have the [parser.HasMoreFlag] set. Use the [Param] type
 | |
| // to unpack the parameters.
 | |
| //
 | |
| // Example:
 | |
| //
 | |
| //	var state byte // the initial state is always zero [NormalState]
 | |
| //	p := NewParser(32, 1024) // create a new parser with a 32 params buffer and 1024 data buffer (optional)
 | |
| //	input := []byte("\x1b[31mHello, World!\x1b[0m")
 | |
| //	for len(input) > 0 {
 | |
| //		seq, width, n, newState := DecodeSequence(input, state, p)
 | |
| //		log.Printf("seq: %q, width: %d", seq, width)
 | |
| //		state = newState
 | |
| //		input = input[n:]
 | |
| //	}
 | |
| func (m Method) DecodeSequence(data []byte, state byte, p *Parser) (seq []byte, width, n int, newState byte) {
 | |
| 	return decodeSequence(m, data, state, p)
 | |
| }
 | |
| 
 | |
| // DecodeSequenceInString decodes the first ANSI escape sequence or a printable
 | |
| // grapheme from the given data. It returns the sequence slice, the number of
 | |
| // bytes read, the cell width for each sequence, and the new state.
 | |
| //
 | |
| // The cell width will always be 0 for control and escape sequences, 1 for
 | |
| // ASCII printable characters, and the number of cells other Unicode characters
 | |
| // occupy. It uses the uniseg package to calculate the width of Unicode
 | |
| // graphemes and characters. This means it will always do grapheme clustering
 | |
| // (mode 2027).
 | |
| //
 | |
| // Passing a non-nil [*Parser] as the last argument will allow the decoder to
 | |
| // collect sequence parameters, data, and commands. The parser cmd will have
 | |
| // the packed command value that contains intermediate and prefix characters.
 | |
| // In the case of a OSC sequence, the cmd will be the OSC command number. Use
 | |
| // [Cmd] and [Param] types to unpack command intermediates and prefixes as well
 | |
| // as parameters.
 | |
| //
 | |
| // Zero [Cmd] means the CSI, DCS, or ESC sequence is invalid. Moreover, checking the
 | |
| // validity of other data sequences, OSC, DCS, etc, will require checking for
 | |
| // the returned sequence terminator bytes such as ST (ESC \\) and BEL).
 | |
| //
 | |
| // We store the command byte in [Cmd] in the most significant byte, the
 | |
| // prefix byte in the next byte, and the intermediate byte in the least
 | |
| // significant byte. This is done to avoid using a struct to store the command
 | |
| // and its intermediates and prefixes. The command byte is always the least
 | |
| // significant byte i.e. [Cmd & 0xff]. Use the [Cmd] type to unpack the
 | |
| // command, intermediate, and prefix bytes. Note that we only collect the last
 | |
| // prefix character and intermediate byte.
 | |
| //
 | |
| // The [p.Params] slice will contain the parameters of the sequence. Any
 | |
| // sub-parameter will have the [parser.HasMoreFlag] set. Use the [Param] type
 | |
| // to unpack the parameters.
 | |
| //
 | |
| // Example:
 | |
| //
 | |
| //	var state byte // the initial state is always zero [NormalState]
 | |
| //	p := NewParser(32, 1024) // create a new parser with a 32 params buffer and 1024 data buffer (optional)
 | |
| //	input := []byte("\x1b[31mHello, World!\x1b[0m")
 | |
| //	for len(input) > 0 {
 | |
| //		seq, width, n, newState := DecodeSequenceInString(input, state, p)
 | |
| //		log.Printf("seq: %q, width: %d", seq, width)
 | |
| //		state = newState
 | |
| //		input = input[n:]
 | |
| //	}
 | |
| func (m Method) DecodeSequenceInString(data string, state byte, p *Parser) (seq string, width, n int, newState byte) {
 | |
| 	return decodeSequence(m, data, state, p)
 | |
| }
 |