class ANSI::String
IMPORTANT! ANSI::String is experimental!!!
ANSI::String stores a regular string (`@text`) and an associative array that ties a character index to an ANSI code (`marks`). For example is we have the string:
"Big Apple"
And applied the color red to it, the marks list would be:
[[0, :red], [9, :clear]]
TODO: In the future we may be able to subclass String, instead of delegating via @text, but not until it is more compatible.
Constants
- CLR
Attributes
Public Class Methods
New Ansi::String
# File lib/ansi/string.rb, line 33 def initialize(text=nil, marks=nil) @text = (text || '').to_s @marks = marks || [] yield(self) if block_given? end
Public Instance Methods
Add one String to another, or to a regular String.
# File lib/ansi/string.rb, line 73 def +(other) case other when ANSI::String ntext = text + other.text nmarks = marks.dup omarks = shift_marks(0, text.size, other.marks) omarks.each{ |(i, c)| nmarks << [i,c] } else ntext = text + other.to_s nmarks = marks.dup end self.class.new(ntext, nmarks) end
# File lib/ansi/string.rb, line 194 def ansi(code) m = marks.dup m.unshift([0, code]) m.push([size, :clear]) self.class.new(text, m) end
# File lib/ansi/string.rb, line 204 def ansi!(code) marks.unshift([0, code]) marks.push([size, :clear]) end
# File lib/ansi/string.rb, line 214 def black ; color(:black) ; end
# File lib/ansi/string.rb, line 225 def black! ; color!(:black) ; end
# File lib/ansi/string.rb, line 213 def blue ; color(:blue) ; end
# File lib/ansi/string.rb, line 224 def blue! ; color!(:blue) ; end
# File lib/ansi/string.rb, line 219 def bold ; ansi(:bold) ; end
# File lib/ansi/string.rb, line 230 def bold! ; ansi!(:bold) ; end
# File lib/ansi/string.rb, line 217 def cyan ; color(:cyan) ; end
# File lib/ansi/string.rb, line 228 def cyan! ; color!(:cyan) ; end
Downcase the string.
# File lib/ansi/string.rb, line 69 def downcase ; self.class.new(text.downcase, marks) ; end
# File lib/ansi/string.rb, line 70 def downcase! ; text.upcase! ; end
# File lib/ansi/string.rb, line 212 def green ; color(:green) ; end
# File lib/ansi/string.rb, line 223 def green! ; color!(:green) ; end
See gsub!.
# File lib/ansi/string.rb, line 189 def gsub(pattern, replacement=nil, &block) dup.gsub!(pattern, replacement, &block) end
# File lib/ansi/string.rb, line 163 def gsub!(pattern, replacement=nil, &block) mark_changes = [] mark_additions = [] text = @text.gsub(pattern) do |s| index = $~.begin(0) replacement = block.call(self.class.new(s)) if block_given? if self.class===replacement adj_marks = replacement.marks.map{ |(i,c)| [i+index,c] } mark_additions.concat(adj_marks) replacement = replacement.text end delta = (replacement.size - s.size) mark_changes << [index, delta] replacement end marks = @marks mark_changes.each do |(index, delta)| marks = shift_marks(index, delta, marks) end marks.concat(mark_additions) @text = text @marks = marks self end
# File lib/ansi/string.rb, line 215 def magenta ; color(:magenta) ; end
# File lib/ansi/string.rb, line 226 def magenta! ; color!(:magenta) ; end
# File lib/ansi/string.rb, line 211 def red ; color(:red) ; end
# File lib/ansi/string.rb, line 222 def red! ; color!(:red) ; end
The size of the base text.
# File lib/ansi/string.rb, line 62 def size ; text.size ; end
slice
# File lib/ansi/string.rb, line 98 def slice(*args) if args.size == 2 index, len = *args endex = index+len new_text = text[index, len] new_marks = [] marks.each do |(i, v)| new_marks << [i, v] if i >= index && i < endex end self.class.new(new_text, new_marks) elsif args.size == 1 rng = args.first case rng when Range index, endex = rng.begin, rng.end new_text = text[rng] new_marks = [] marks.each do |(i, v)| new_marks << [i, v] if i >= index && i < endex end self.class.new(new_text, new_marks) else nm = marks.select do |(i, v)| #marks[0] == rng or ( marks[0] == rng + 1 && [:clear, :reset].include?(marks[1]) ) i == rng or ( i == rng + 1 && [:clear, :reset].include?(v) ) end self.class.new(text[rng,1], nm) end else raise ArgumentError end end
See sub!.
# File lib/ansi/string.rb, line 158 def sub(pattern,replacement=nil, &block) dup.sub!(pattern, replacement, &block) end
This is more limited than the normal String
method. It does not yet support a block, and replacement
won't substitue for 1, 2, etc.
TODO: block support.
# File lib/ansi/string.rb, line 139 def sub!(pattern, replacement=nil, &block) mark_changes = [] text = @text.sub(pattern) do |s| index = $~.begin(0) replacement = block.call(s) if block_given? delta = (replacement.size - s.size) mark_changes << [index, delta] replacement end marks = @marks mark_changes.each do |index, delta| marks = shift_marks(index, delta, marks) end @text = text @marks = marks self end
Convert Ansi::String object to normal String. This converts the intental markup codes to ANSI codes.
# File lib/ansi/string.rb, line 41 def to_s s = text.dup m = marks.sort do |a,b| v = b[0] <=> a[0] if v == 0 (b[1] == :clear or b[1] == :reset) ? -1 : 1 else v end end m.each do |(index, code)| s.insert(index, ANSI::Code.__send__(code)) end #s << CLR unless s =~ /#{Regexp.escape(CLR)}$/ # always end with a clear s end
# File lib/ansi/string.rb, line 220 def underline ; ansi(:underline) ; end
# File lib/ansi/string.rb, line 231 def underline! ; ansi!(:underline) ; end
Upcase the string.
# File lib/ansi/string.rb, line 65 def upcase ; self.class.new(text.upcase, marks) ; end
# File lib/ansi/string.rb, line 66 def upcase! ; text.upcase! ; end
# File lib/ansi/string.rb, line 216 def yellow ; color(:yellow) ; end
# File lib/ansi/string.rb, line 227 def yellow! ; color!(:yellow) ; end
Private Instance Methods
# File lib/ansi/string.rb, line 236 def shift_marks(index, delta, marks=nil) new_marks = [] (marks || @marks).each do |(i, c)| case i <=> index when -1 new_marks << [i, c] when 0, 1 new_marks << [i+delta, c] end end new_marks end
# File lib/ansi/string.rb, line 250 def shift_marks!(index, delta) @marks.replace(shift_marks(index, delta)) end