Class: RDoc::Markup::AttributeManager
Relationships & Source Files | |
Inherits: | Object |
Defined in: | lib/rdoc/markup/attribute_manager.rb |
Overview
Manages changes of attributes in a block of text
Constant Summary
-
NULL =
The NUL character
"\000".freeze
Class Method Summary
-
.new ⇒ AttributeManager
constructor
Creates a new attribute manager that understands bold, emphasized and teletype text.
Instance Attribute Summary
-
#attributes
readonly
The attributes enabled for this markup object.
-
#html_tags
readonly
This maps HTML tags to the corresponding attribute char.
-
#matching_word_pairs
readonly
This maps delimiters that occur around words (such as bold or
tt
) where the start and end delimiters and the same. -
#protectable
readonly
A \ in front of a character that would normally be processed turns off processing.
-
#special
readonly
And this maps special sequences to a name.
-
#word_pair_map
readonly
And this is used when the delimiters aren't the same.
Instance Method Summary
-
#add_html(tag, name)
Adds a markup class with
name
for words surrounded by HTML tagtag
. -
#add_special(pattern, name)
Adds a special handler for
pattern
withname
. -
#add_word_pair(start, stop, name)
Adds a markup class with
name
for words wrapped in thestart
andstop
character. -
#attribute(turn_on, turn_off)
Return an attribute object with the given turn_on and turn_off bits set.
-
#change_attribute(current, new)
Changes the current attribute from
current
to .new -
#changed_attribute_by_name(current_set, new_set)
Used by the tests to change attributes by name from
current_set
tonew_set
-
#convert_attrs(str, attrs)
Map attributes like textto the sequence 001002<char>001003<char>, where <char> is a per-attribute specific character.
-
#convert_html(str, attrs)
Converts HTML tags to ::RDoc::RDoc attributes.
-
#convert_specials(str, attrs)
Converts special sequences to ::RDoc::RDoc attributes.
-
#copy_string(start_pos, end_pos)
Copies
start_pos
toend_pos
from the current string. -
#display_attributes
Debug method that prints a string along with its attributes.
-
#flow(str)
Processes
str
converting attributes, HTML and specials. -
#mask_protected_sequences
Escapes special sequences of text to prevent conversion to ::RDoc::RDoc.
-
#split_into_flow
Splits the string into chunks by attribute change.
-
#unmask_protected_sequences
Unescapes special sequences of text.
Constructor Details
.new ⇒ AttributeManager
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
Instance Attribute Details
#attributes (readonly)
The attributes enabled for this markup object.
# File 'lib/rdoc/markup/attribute_manager.rb', line 28
attr_reader :attributes
#html_tags (readonly)
This maps HTML tags to the corresponding attribute char
# File 'lib/rdoc/markup/attribute_manager.rb', line 46
attr_reader :
#matching_word_pairs (readonly)
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
# File 'lib/rdoc/markup/attribute_manager.rb', line 35
attr_reader :matching_word_pairs
#protectable (readonly)
A \ in front of a character that would normally be processed turns off processing. We do this by turning < into <#PROTECT
# File 'lib/rdoc/markup/attribute_manager.rb', line 52
attr_reader :protectable
#special (readonly)
And this maps special sequences to a name. A special sequence is something like a WikiWord
# File 'lib/rdoc/markup/attribute_manager.rb', line 58
attr_reader :special
#word_pair_map (readonly)
And this is used when the delimiters aren't the same. In this case the hash maps a pattern to the attribute character
# File 'lib/rdoc/markup/attribute_manager.rb', line 41
attr_reader :word_pair_map
Instance Method Details
#add_html(tag, name)
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)
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)
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)
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)
Changes the current attribute from current
to .new
#changed_attribute_by_name(current_set, new_set)
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)
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 = @matching_word_pairs.keys.join("") re = /(^|\W)([#{}])([#\\]?[\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)
Converts HTML tags to ::RDoc::RDoc attributes
# File 'lib/rdoc/markup/attribute_manager.rb', line 155
def convert_html(str, attrs) = @html_tags.keys.join '|' 1 while str.gsub!(/<(#{})>(.*?)<\/\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)
Converts special sequences to ::RDoc::RDoc attributes
#copy_string(start_pos, end_pos)
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
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)
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
Escapes special sequences of text to prevent conversion to ::RDoc::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
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
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