Class: ANSI::String

Inherits:
Object
  • Object
show all
Defined in:
lib/ansi/string.rb

Overview

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.

Constant Summary collapse

CLR =
ANSI::Code::CLEAR

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(text = nil, marks = nil) {|_self| ... } ⇒ String

New Ansi::String

Yields:

  • (_self)

Yield Parameters:

  • _self (ANSI::String)

    the object that the method was called on



33
34
35
36
37
# 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

Instance Attribute Details

#marksObject (readonly)

Returns the value of attribute marks.



30
31
32
# File 'lib/ansi/string.rb', line 30

def marks
  @marks
end

#textObject (readonly)

Returns the value of attribute text.



29
30
31
# File 'lib/ansi/string.rb', line 29

def text
  @text
end

Instance Method Details

#+(other) ⇒ Object

Add one String to another, or to a regular String.



73
74
75
76
77
78
79
80
81
82
83
84
85
# 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

#ansi(code) ⇒ Object Also known as: color



193
194
195
196
197
198
# File 'lib/ansi/string.rb', line 193

def ansi(code)
  m = marks.dup
  m.unshift([0, code])
  m.push([size, :clear])
  self.class.new(text, m)
end

#ansi!(code) ⇒ Object Also known as: color!



203
204
205
206
# File 'lib/ansi/string.rb', line 203

def ansi!(code)
  marks.unshift([0, code])
  marks.push([size, :clear])
end

#blackObject



213
# File 'lib/ansi/string.rb', line 213

def black      ; color(:black)    ; end

#black!Object



224
# File 'lib/ansi/string.rb', line 224

def black!     ; color!(:black)   ; end

#blueObject



212
# File 'lib/ansi/string.rb', line 212

def blue       ; color(:blue)     ; end

#blue!Object



223
# File 'lib/ansi/string.rb', line 223

def blue!      ; color!(:blue)    ; end

#boldObject



218
# File 'lib/ansi/string.rb', line 218

def bold       ; ansi(:bold)       ; end

#bold!Object



229
# File 'lib/ansi/string.rb', line 229

def bold!      ; ansi!(:bold)      ; end

#cyanObject



216
# File 'lib/ansi/string.rb', line 216

def cyan       ; color(:cyan)     ; end

#cyan!Object



227
# File 'lib/ansi/string.rb', line 227

def cyan!      ; color!(:cyan)    ; end

#downcaseObject

Downcase the string.



69
# File 'lib/ansi/string.rb', line 69

def downcase  ; self.class.new(text.downcase, marks) ; end

#downcase!Object



70
# File 'lib/ansi/string.rb', line 70

def downcase! ; text.upcase! ; end

#greenObject



211
# File 'lib/ansi/string.rb', line 211

def green      ; color(:green)    ; end

#green!Object



222
# File 'lib/ansi/string.rb', line 222

def green!     ; color!(:green)   ; end

#gsub(pattern, replacement = nil, &block) ⇒ Object

See #gsub!.



188
189
190
# File 'lib/ansi/string.rb', line 188

def gsub(pattern, replacement=nil, &block)
  dup.gsub!(pattern, replacement, &block)
end

#gsub!(pattern, replacement = nil, &block) ⇒ Object



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/ansi/string.rb', line 162

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

#magentaObject



214
# File 'lib/ansi/string.rb', line 214

def magenta    ; color(:magenta)  ; end

#magenta!Object



225
# File 'lib/ansi/string.rb', line 225

def magenta!   ; color!(:magenta) ; end

#redObject



210
# File 'lib/ansi/string.rb', line 210

def red        ; color(:red)      ; end

#red!Object



221
# File 'lib/ansi/string.rb', line 221

def red!       ; color!(:red)     ; end

#shift_marks(index, delta, marks = nil) ⇒ Object (private)



235
236
237
238
239
240
241
242
243
244
245
246
# File 'lib/ansi/string.rb', line 235

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) ⇒ Object (private)



249
250
251
# File 'lib/ansi/string.rb', line 249

def shift_marks!(index, delta)
  @marks.replace(shift_marks(index, delta))
end

#sizeObject

The size of the base text.



62
# File 'lib/ansi/string.rb', line 62

def size ; text.size ; end

#slice(*args) ⇒ Object Also known as: []

slice



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# 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,c)|
        marks[0] == rng or ( marks[0] == rng + 1 && [:clear, :reset].include?(marks[1]) )
      end
      self.class.new(text[rng,1], nm)
    end
  else
    raise ArgumentError
  end
end

#sub(pattern, replacement = nil, &block) ⇒ Object

See #sub!.



157
158
159
# File 'lib/ansi/string.rb', line 157

def sub(pattern,replacement=nil, &block)
  dup.sub!(pattern, replacement, &block)
end

#sub!(pattern, replacement = nil, &block) ⇒ Object

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.



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/ansi/string.rb', line 138

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_sObject Also known as: to_str

Convert Ansi::String object to normal String. This converts the intental markup codes to ANSI codes.



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# 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

#underlineObject



219
# File 'lib/ansi/string.rb', line 219

def underline  ; ansi(:underline)  ; end

#underline!Object



230
# File 'lib/ansi/string.rb', line 230

def underline! ; ansi!(:underline) ; end

#upcaseObject

Upcase the string.



65
# File 'lib/ansi/string.rb', line 65

def upcase  ; self.class.new(text.upcase, marks) ; end

#upcase!Object



66
# File 'lib/ansi/string.rb', line 66

def upcase! ; text.upcase! ; end

#yellowObject



215
# File 'lib/ansi/string.rb', line 215

def yellow     ; color(:yellow)   ; end

#yellow!Object



226
# File 'lib/ansi/string.rb', line 226

def yellow!    ; color!(:yellow)  ; end