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


194
195
196
197
198
199
# 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

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


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

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

#blackObject


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

def black      ; color(:black)    ; end

#black!Object


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

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

#blueObject


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

def blue       ; color(:blue)     ; end

#blue!Object


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

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

#boldObject


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

def bold       ; ansi(:bold)       ; end

#bold!Object


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

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

#cyanObject


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

def cyan       ; color(:cyan)     ; end

#cyan!Object


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

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


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

def green      ; color(:green)    ; end

#green!Object


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

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

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

See #gsub!.


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

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

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


163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# 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

#magentaObject


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

def magenta    ; color(:magenta)  ; end

#magenta!Object


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

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

#redObject


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

def red        ; color(:red)      ; end

#red!Object


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

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

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


236
237
238
239
240
241
242
243
244
245
246
247
# 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) ⇒ Object (private)


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

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
129
# 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

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

See #sub!.


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

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.


139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# 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_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


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

def underline  ; ansi(:underline)  ; end

#underline!Object


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

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


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

def yellow     ; color(:yellow)   ; end

#yellow!Object


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

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