Extended maintenance of Ruby 1.9.3 ended on February 23, 2015. Read more
Object
Manages changes of attributes in a block of text
The NUL character
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
Creates a new attribute manager that understands bold, emphasized and teletype text.
# File 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 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 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 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 = /(#{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 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 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 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 rdoc/markup/attribute_manager.rb, line 123 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
Converts HTML tags to RDoc attributes
# File rdoc/markup/attribute_manager.rb, line 149 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
Converts special sequences to RDoc attributes
# File 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 rdoc/markup/attribute_manager.rb, line 112 def copy_string(start_pos, end_pos) res = @str[start_pos...end_pos] res.gsub!(/\000/, '') res end
Debug method that prints a string along with its attributes
# File 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 =~ /^ *$/ bit <<= 1 end end
Processes str
converting attributes, HTML and specials
# File 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 rdoc/markup/attribute_manager.rb, line 178 def mask_protected_sequences # protect __send__, __FILE__, etc. @str.gsub!(/__([a-z]+)__/i, "_#{PROTECT_ATTR}_#{PROTECT_ATTR}\\1_#{PROTECT_ATTR}_#{PROTECT_ATTR}") @str.gsub!(/\([#{Regexp.escape @protectable.join('')}])/, "\\1#{PROTECT_ATTR}") end
Splits the string into chunks by attribute change
# File 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 == "\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 & 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 == "\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
Commenting is here to help enhance the documentation. For example, code samples, or clarification of the documentation.
If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.
If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.
If you want to help improve the Ruby documentation, please visit Documenting-ruby.org.