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

marks[R]
text[R]

Public Class Methods

new(text=nil, marks=nil) { |self| ... } click to toggle source

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

+(other) click to toggle source

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
[](*args)
Alias for: slice
ansi(code) click to toggle source
# 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
Also aliased as: color
ansi!(code) click to toggle source
# File lib/ansi/string.rb, line 204
def ansi!(code)
  marks.unshift([0, code])
  marks.push([size, :clear])
end
Also aliased as: color!
black() click to toggle source
# File lib/ansi/string.rb, line 214
def black      ; color(:black)    ; end
black!() click to toggle source
# File lib/ansi/string.rb, line 225
def black!     ; color!(:black)   ; end
blue() click to toggle source
# File lib/ansi/string.rb, line 213
def blue       ; color(:blue)     ; end
blue!() click to toggle source
# File lib/ansi/string.rb, line 224
def blue!      ; color!(:blue)    ; end
bold() click to toggle source
# File lib/ansi/string.rb, line 219
def bold       ; ansi(:bold)       ; end
bold!() click to toggle source
# File lib/ansi/string.rb, line 230
def bold!      ; ansi!(:bold)      ; end
color(code)
Alias for: ansi
color!(code)
Alias for: ansi!
cyan() click to toggle source
# File lib/ansi/string.rb, line 217
def cyan       ; color(:cyan)     ; end
cyan!() click to toggle source
# File lib/ansi/string.rb, line 228
def cyan!      ; color!(:cyan)    ; end
downcase() click to toggle source

Downcase the string.

# File lib/ansi/string.rb, line 69
def downcase  ; self.class.new(text.downcase, marks) ; end
downcase!() click to toggle source
# File lib/ansi/string.rb, line 70
def downcase! ; text.upcase! ; end
green() click to toggle source
# File lib/ansi/string.rb, line 212
def green      ; color(:green)    ; end
green!() click to toggle source
# File lib/ansi/string.rb, line 223
def green!     ; color!(:green)   ; end
gsub(pattern, replacement=nil, &block) click to toggle source

See gsub!.

# File lib/ansi/string.rb, line 189
def gsub(pattern, replacement=nil, &block)
  dup.gsub!(pattern, replacement, &block)
end
gsub!(pattern, replacement=nil, &block) click to toggle source
# 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
magenta() click to toggle source
# File lib/ansi/string.rb, line 215
def magenta    ; color(:magenta)  ; end
magenta!() click to toggle source
# File lib/ansi/string.rb, line 226
def magenta!   ; color!(:magenta) ; end
red() click to toggle source
# File lib/ansi/string.rb, line 211
def red        ; color(:red)      ; end
red!() click to toggle source
# File lib/ansi/string.rb, line 222
def red!       ; color!(:red)     ; end
size() click to toggle source

The size of the base text.

# File lib/ansi/string.rb, line 62
def size ; text.size ; end
slice(*args) click to toggle source

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
Also aliased as: []
sub(pattern,replacement=nil, &block) click to toggle source

See sub!.

# File lib/ansi/string.rb, line 158
def sub(pattern,replacement=nil, &block)
  dup.sub!(pattern, replacement, &block)
end
sub!(pattern, replacement=nil, &block) click to toggle source

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
to_s() click to toggle source

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
Also aliased as: to_str
to_str()

ANSI::String is a type of String.

Alias for: to_s
underline() click to toggle source
# File lib/ansi/string.rb, line 220
def underline  ; ansi(:underline)  ; end
underline!() click to toggle source
# File lib/ansi/string.rb, line 231
def underline! ; ansi!(:underline) ; end
upcase() click to toggle source

Upcase the string.

# File lib/ansi/string.rb, line 65
def upcase  ; self.class.new(text.upcase, marks) ; end
upcase!() click to toggle source
# File lib/ansi/string.rb, line 66
def upcase! ; text.upcase! ; end
yellow() click to toggle source
# File lib/ansi/string.rb, line 216
def yellow     ; color(:yellow)   ; end
yellow!() click to toggle source
# File lib/ansi/string.rb, line 227
def yellow!    ; color!(:yellow)  ; end

Private Instance Methods

shift_marks(index, delta, marks=nil) click to toggle source
# 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
shift_marks!(index, delta) click to toggle source
# File lib/ansi/string.rb, line 250
def shift_marks!(index, delta)
  @marks.replace(shift_marks(index, delta))
end