class RDoc::Markup::AttributeManager

Manages changes of attributes in a block of text

Constants

NULL

The NUL character

Attributes

attributes[R]

The attributes enabled for this markup object.

html_tags[R]

This maps HTML tags to the corresponding attribute char

matching_word_pairs[R]

This maps delimiters that occur around words (such as bold or tt) where the start and end delimiters and the same. This lets us optimize the regexp

protectable[R]

A \ in front of a character that would normally be processed turns off processing. We do this by turning < into <#{PROTECT}

special[R]

And this maps special sequences to a name. A special sequence is something like a WikiWord

word_pair_map[R]

And this is used when the delimiters aren't the same. In this case the hash maps a pattern to the attribute character

Public Class Methods

new() click to toggle source

Creates a new attribute manager that understands bold, emphasized and teletype text.

# File lib/rdoc/markup/attribute_manager.rb, line 64
def initialize
 @html_tags = {}
 @matching_word_pairs = {}
 @protectable = %w[<]
 @special = []
 @word_pair_map = {}
 @attributes = RDoc::Markup::Attributes.new
 add_word_pair "*", "*", :BOLD
 add_word_pair "_", "_", :EM
 add_word_pair "+", "+", :TT
 add_html "em", :EM
 add_html "i", :EM
 add_html "b", :BOLD
 add_html "tt", :TT
 add_html "code", :TT
end

Public Instance Methods

add_html(tag, name) click to toggle source

Adds a markup class with name for words surrounded by HTML tag tag. To process emphasis tags:

am.add_html 'em', :EM
# File lib/rdoc/markup/attribute_manager.rb, line 230
def add_html(tag, name)
 @html_tags[tag.downcase] = @attributes.bitmap_for name
end
add_special(pattern, name) click to toggle source

Adds a special handler for pattern with name. A simple URL handler would be:

@am.add_special(/((https?:)\S+\w)/, :HYPERLINK)
# File lib/rdoc/markup/attribute_manager.rb, line 240
def add_special pattern, name
 @special << [pattern, @attributes.bitmap_for(name)]
end
add_word_pair(start, stop, name) click to toggle source

Adds a markup class with name for words wrapped in the start and stop character. To make words wrapped with "*" bold:

am.add_word_pair '*', '*', :BOLD
# File lib/rdoc/markup/attribute_manager.rb, line 207
def add_word_pair(start, stop, name)
 raise ArgumentError, "Word flags may not start with '<'" if
 start[0,1] == '<'
 bitmap = @attributes.bitmap_for name
 if start == stop then
 @matching_word_pairs[start] = bitmap
 else
 pattern = /(#{Regexp.escape start})(\S+)(#{Regexp.escape stop})/
 @word_pair_map[pattern] = bitmap
 end
 @protectable << start[0,1]
 @protectable.uniq!
end
attribute(turn_on, turn_off) click to toggle source

Return an attribute object with the given turn_on and turn_off bits set

# File lib/rdoc/markup/attribute_manager.rb, line 86
def attribute(turn_on, turn_off)
 RDoc::Markup::AttrChanger.new turn_on, turn_off
end
change_attribute(current, new) click to toggle source

Changes the current attribute from current to new

# File lib/rdoc/markup/attribute_manager.rb, line 93
def change_attribute current, new
 diff = current ^ new
 attribute(new & diff, current & diff)
end
changed_attribute_by_name(current_set, new_set) click to toggle source

Used by the tests to change attributes by name from current_set to new_set

# File lib/rdoc/markup/attribute_manager.rb, line 102
def changed_attribute_by_name current_set, new_set
 current = new = 0
 current_set.each do |name|
 current |= @attributes.bitmap_for(name)
 end
 new_set.each do |name|
 new |= @attributes.bitmap_for(name)
 end
 change_attribute(current, new)
end
convert_attrs(str, attrs) click to toggle source

Map attributes like textto the sequence 001002<char>001003<char>, where <char> is a per-attribute specific character

# File lib/rdoc/markup/attribute_manager.rb, line 129
def convert_attrs(str, attrs)
 # first do matching ones
 tags = @matching_word_pairs.keys.join("")
 re = /(^|\W)([#{tags}])([#:\]?[\w.\/-]+?\S?)2円(\W|$)/
 1 while str.gsub!(re) do
 attr = @matching_word_pairs[2ドル]
 attrs.set_attrs($`.length + 1ドル.length + 2ドル.length, 3ドル.length, attr)
 1ドル + NULL * 2ドル.length + 3ドル + NULL * 2ドル.length + 4ドル
 end
 # then non-matching
 unless @word_pair_map.empty? then
 @word_pair_map.each do |regexp, attr|
 str.gsub!(regexp) {
 attrs.set_attrs($`.length + 1ドル.length, 2ドル.length, attr)
 NULL * 1ドル.length + 2ドル + NULL * 3ドル.length
 }
 end
 end
end
convert_html(str, attrs) click to toggle source

Converts HTML tags to RDoc attributes

# File lib/rdoc/markup/attribute_manager.rb, line 155
def convert_html(str, attrs)
 tags = @html_tags.keys.join '|'
 1 while str.gsub!(/<(#{tags})>(.*?)<\/1円>/i) {
 attr = @html_tags[1ドル.downcase]
 html_length = 1ドル.length + 2
 seq = NULL * html_length
 attrs.set_attrs($`.length + html_length, 2ドル.length, attr)
 seq + 2ドル + seq + NULL
 }
end
convert_specials(str, attrs) click to toggle source

Converts special sequences to RDoc attributes

# File lib/rdoc/markup/attribute_manager.rb, line 170
def convert_specials str, attrs
 @special.each do |regexp, attribute|
 str.scan(regexp) do
 capture = $~.size == 1 ? 0 : 1
 s, e = $~.offset capture
 attrs.set_attrs s, e - s, attribute | @attributes.special
 end
 end
end
copy_string(start_pos, end_pos) click to toggle source

Copies start_pos to end_pos from the current string

# File lib/rdoc/markup/attribute_manager.rb, line 118
def copy_string(start_pos, end_pos)
 res = @str[start_pos...end_pos]
 res.gsub!(/000円/, '')
 res
end
display_attributes() click to toggle source

Debug method that prints a string along with its attributes

# File lib/rdoc/markup/attribute_manager.rb, line 266
def display_attributes
 puts
 puts @str.tr(NULL, "!")
 bit = 1
 16.times do |bno|
 line = ""
 @str.length.times do |i|
 if (@attrs[i] & bit) == 0
 line << " "
 else
 if bno.zero?
 line << "S"
 else
 line << ("%d" % (bno+1))
 end
 end
 end
 puts(line) unless line =~ /^ *$/
 bit <<= 1
 end
end
flow(str) click to toggle source

Processes str converting attributes, HTML and specials

# File lib/rdoc/markup/attribute_manager.rb, line 247
def flow str
 @str = str
 mask_protected_sequences
 @attrs = RDoc::Markup::AttrSpan.new @str.length
 convert_attrs @str, @attrs
 convert_html @str, @attrs
 convert_specials @str, @attrs
 unmask_protected_sequences
 split_into_flow
end
mask_protected_sequences() click to toggle source

Escapes special sequences of text to prevent conversion to RDoc

# File lib/rdoc/markup/attribute_manager.rb, line 185
def mask_protected_sequences
 # protect __send__, __FILE__, etc.
 @str.gsub!(/__([a-z]+)__/i,
 "_#{PROTECT_ATTR}_#{PROTECT_ATTR}\1円_#{PROTECT_ATTR}_#{PROTECT_ATTR}")
 @str.gsub!(/(\A|[^\])\([#{Regexp.escape @protectable.join}])/m,
 "\1円\2円#{PROTECT_ATTR}")
 @str.gsub!(/\(\[#{Regexp.escape @protectable.join}])/m, "\1円")
end
split_into_flow() click to toggle source

Splits the string into chunks by attribute change

# File lib/rdoc/markup/attribute_manager.rb, line 291
def split_into_flow
 res = []
 current_attr = 0
 str_len = @str.length
 # skip leading invisible text
 i = 0
 i += 1 while i < str_len and @str[i].chr == "0円"
 start_pos = i
 # then scan the string, chunking it on attribute changes
 while i < str_len
 new_attr = @attrs[i]
 if new_attr != current_attr
 if i > start_pos
 res << copy_string(start_pos, i)
 start_pos = i
 end
 res << change_attribute(current_attr, new_attr)
 current_attr = new_attr
 if (current_attr & @attributes.special) != 0 then
 i += 1 while
 i < str_len and (@attrs[i] & @attributes.special) != 0
 res << RDoc::Markup::Special.new(current_attr,
 copy_string(start_pos, i))
 start_pos = i
 next
 end
 end
 # move on, skipping any invisible characters
 begin
 i += 1
 end while i < str_len and @str[i].chr == "0円"
 end
 # tidy up trailing text
 if start_pos < str_len
 res << copy_string(start_pos, str_len)
 end
 # and reset to all attributes off
 res << change_attribute(current_attr, 0) if current_attr != 0
 res
end
unmask_protected_sequences() click to toggle source

Unescapes special sequences of text

# File lib/rdoc/markup/attribute_manager.rb, line 197
def unmask_protected_sequences
 @str.gsub!(/(.)#{PROTECT_ATTR}/, "\1円000円")
end