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.

iterator.go 1.7KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. package chroma
  2. import "strings"
  3. // An Iterator across tokens.
  4. //
  5. // nil will be returned at the end of the Token stream.
  6. //
  7. // If an error occurs within an Iterator, it may propagate this in a panic. Formatters should recover.
  8. type Iterator func() Token
  9. // Tokens consumes all tokens from the iterator and returns them as a slice.
  10. func (i Iterator) Tokens() []Token {
  11. var out []Token
  12. for t := i(); t != EOF; t = i() {
  13. out = append(out, t)
  14. }
  15. return out
  16. }
  17. // Concaterator concatenates tokens from a series of iterators.
  18. func Concaterator(iterators ...Iterator) Iterator {
  19. return func() Token {
  20. for len(iterators) > 0 {
  21. t := iterators[0]()
  22. if t != EOF {
  23. return t
  24. }
  25. iterators = iterators[1:]
  26. }
  27. return EOF
  28. }
  29. }
  30. // Literator converts a sequence of literal Tokens into an Iterator.
  31. func Literator(tokens ...Token) Iterator {
  32. return func() Token {
  33. if len(tokens) == 0 {
  34. return EOF
  35. }
  36. token := tokens[0]
  37. tokens = tokens[1:]
  38. return token
  39. }
  40. }
  41. // SplitTokensIntoLines splits tokens containing newlines in two.
  42. func SplitTokensIntoLines(tokens []Token) (out [][]Token) {
  43. var line []Token // nolint: prealloc
  44. for _, token := range tokens {
  45. for strings.Contains(token.Value, "\n") {
  46. parts := strings.SplitAfterN(token.Value, "\n", 2)
  47. // Token becomes the tail.
  48. token.Value = parts[1]
  49. // Append the head to the line and flush the line.
  50. clone := token.Clone()
  51. clone.Value = parts[0]
  52. line = append(line, clone)
  53. out = append(out, line)
  54. line = nil
  55. }
  56. line = append(line, token)
  57. }
  58. if len(line) > 0 {
  59. out = append(out, line)
  60. }
  61. // Strip empty trailing token line.
  62. if len(out) > 0 {
  63. last := out[len(out)-1]
  64. if len(last) == 1 && last[0].Value == "" {
  65. out = out[:len(out)-1]
  66. }
  67. }
  68. return
  69. }