Class: Termplot::Utils::AnsiSafeString

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/termplot/utils/ansi_safe_string.rb

Constant Summary collapse

ANSI_MATCHER =

Regex to match ANSI escape sequences.

Regexp.new("(\\[?\\033\\[?[;?\\d]*[\\dA-Za-z][\\];]?)")

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(string) ⇒ AnsiSafeString

Returns a new instance of AnsiSafeString.



10
11
12
# File 'lib/termplot/utils/ansi_safe_string.rb', line 10

def initialize(string)
  @string = string
end

Instance Attribute Details

#stringObject (readonly)

Returns the value of attribute string.



9
10
11
# File 'lib/termplot/utils/ansi_safe_string.rb', line 9

def string
  @string
end

Instance Method Details

#each {|current_char| ... } ⇒ Object

Yield each char in the string, folding any escape sequences into the next char. NOTE: If the string includes only ansi escape sequences, nothing will be yielded.

Yields:

  • (current_char)


25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/termplot/utils/ansi_safe_string.rb', line 25

def each
  ansi_code_positions = []

  string.scan(ANSI_MATCHER) do |_|
    ansi_code_positions << Regexp.last_match.offset(0)
  end

  i = 0
  current_char = ""
  while i < string.length
    if ansi_code_positions.any? { |pos| pos[0] <= i && pos[1] > i }
      current_char << string[i]
      i += 1
    else
      current_char << string[i]

      # If the next character is a terminating ansi sequence, we need to
      # fold it into the current character, to prevent emitting an ansi
      # sequence only as the last character.
      next_char_is_terminating_ansi_sequence =
        ansi_code_positions.length > 0 &&
        ansi_code_positions.last[0] == i + 1 &&
        ansi_code_positions.last[1] == string.length

      if next_char_is_terminating_ansi_sequence
        current_char << string[i + 1..-1]
        i += 1 + (string.length - 1 - i + 1)
      else
        yield current_char
        current_char = ""
        i += 1
      end
    end
  end

  yield current_char unless current_char.empty?
end

#lengthObject



14
15
16
# File 'lib/termplot/utils/ansi_safe_string.rb', line 14

def length
  sanitized.length
end

#sanitizedObject



18
19
20
# File 'lib/termplot/utils/ansi_safe_string.rb', line 18

def sanitized
  string.gsub(/#{ANSI_MATCHER}/, "")
end

#slice(start, stop) ⇒ Object



63
64
65
# File 'lib/termplot/utils/ansi_safe_string.rb', line 63

def slice(start, stop)
  AnsiSafeString.new(to_a[start..stop].join)
end