Manages changes of attributes in a block of text
The NUL character
This maps HTML tags to the corresponding attribute char
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
A \ in front of a character that would normally be processed turns off processing. We do this by turning < into <#{PROTECT}
And this maps special sequences to a name. A special sequence is something like a WikiWord
And this is used when the delimiters aren’t the same. In this case the hash maps a pattern to the attribute character
Creates a new attribute manager that understands bold, emphasized and teletype text.
# File lib/rdoc/markup/attribute_manager.rb, line 59
def initialize
  @html_tags = {}
  @matching_word_pairs = {}
  @protectable = %w[<]
  @special = {}
  @word_pair_map = {}
  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
						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 222
def add_html(tag, name)
  @html_tags[tag.downcase] = RDoc::Markup::Attribute.bitmap_for name
end
						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 232
def add_special(pattern, name)
  @special[pattern] = RDoc::Markup::Attribute.bitmap_for name
end
						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 199
def add_word_pair(start, stop, name)
  raise ArgumentError, "Word flags may not start with '<'" if
    start[0,1] == '<'
  bitmap = RDoc::Markup::Attribute.bitmap_for name
  if start == stop then
    @matching_word_pairs[start] = bitmap
  else
    pattern = %r(#{Regexp.escape start})(\S+)(#{Regexp.escape stop})/
    @word_pair_map[pattern] = bitmap
  end
  @protectable << start[0,1]
  @protectable.uniq!
end
						Return an attribute object with the given turn_on and turn_off bits set
# File lib/rdoc/markup/attribute_manager.rb, line 80
def attribute(turn_on, turn_off)
  RDoc::Markup::AttrChanger.new turn_on, turn_off
end
						Changes the current attribute from current to new
# File lib/rdoc/markup/attribute_manager.rb, line 87
def change_attribute current, new
  diff = current ^ new
  attribute(new & diff, current & diff)
end
						Used by the tests to change attributes by name from
current_set to new_set
# File lib/rdoc/markup/attribute_manager.rb, line 96
def changed_attribute_by_name current_set, new_set
  current = new = 0
  current_set.each do |name|
    current |= RDoc::Markup::Attribute.bitmap_for(name)
  end
  new_set.each do |name|
    new |= RDoc::Markup::Attribute.bitmap_for(name)
  end
  change_attribute(current, new)
end
						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 123
def convert_attrs(str, attrs)
  # first do matching ones
  tags = @matching_word_pairs.keys.join("")
  re = %r(^|\W)([#{tags}])([#:\\]?[\w.\/-]+?\S?)\22((\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
						Converts HTML tags to RDoc attributes
# File lib/rdoc/markup/attribute_manager.rb, line 149
def convert_html(str, attrs)
  tags = @html_tags.keys.join '|'
  1 while str.gsub!(%r<(#{tags})>(.*?)<\/\11>>/) {
    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
						Converts special sequences to RDoc attributes
# File lib/rdoc/markup/attribute_manager.rb, line 164
def convert_specials(str, attrs)
  unless @special.empty?
    @special.each do |regexp, attr|
      str.scan(regexp) do
        attrs.set_attrs($`.length, $&.length,
                        attr | RDoc::Markup::Attribute::SPECIAL)
      end
    end
  end
end
						Copies start_pos to end_pos from the current
string
# File lib/rdoc/markup/attribute_manager.rb, line 112
def copy_string(start_pos, end_pos)
  res = @str[start_pos...end_pos]
  res.gsub!(%r\0000/, '')
  res
end
						Debug method that prints a string along with its attributes
# File lib/rdoc/markup/attribute_manager.rb, line 258
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 =~ %r^ *$/
    bit <<= 1
  end
end
						Processes str converting attributes, HTML and specials
# File lib/rdoc/markup/attribute_manager.rb, line 239
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
						Escapes special sequences of text to prevent conversion to RDoc
# File lib/rdoc/markup/attribute_manager.rb, line 178
def mask_protected_sequences
  # protect __send__, __FILE__, etc.
  @str.gsub!(%r__([a-z]+)__/,
    "_#{PROTECT_ATTR}_#{PROTECT_ATTR}\\1_#{PROTECT_ATTR}_#{PROTECT_ATTR}")
  @str.gsub!(%r\\([#{Regexp.escape @protectable.join('')}])/,
             "\\1#{PROTECT_ATTR}")
end
						Splits the string into chunks by attribute change
# File lib/rdoc/markup/attribute_manager.rb, line 283
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 == "\00""
  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 & RDoc::Markup::Attribute::SPECIAL) != 0 then
        i += 1 while
          i < str_len and (@attrs[i] & RDoc::Markup::Attribute::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 == "\00""
  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
						Unescapes special sequences of text
# File lib/rdoc/markup/attribute_manager.rb, line 189
def unmask_protected_sequences
  @str.gsub!(%r(.)#{PROTECT_ATTR}/, "\\1\0000")
end
						| / | Search | 
|---|---|
| ? | Show this help |