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
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 56
56: def initialize
57: @html_tags = {}
58: @matching_word_pairs = {}
59: @protectable = ]<\\]
60: @special = {}
61: @word_pair_map = {}
62:
63: add_word_pair "*", "*", :BOLD
64: add_word_pair "_", "_", :EM
65: add_word_pair "+", "+", :TT
66:
67: add_html "em", :EM
68: add_html "i", :EM
69: add_html "b", :BOLD
70: add_html "tt", :TT
71: add_html "code", :TT
72: 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 207
207: def add_html(tag, name)
208: @html_tags[tag.downcase] = RDoc::Markup::Attribute.bitmap_for name
209: 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 217
217: def add_special(pattern, name)
218: @special[pattern] = RDoc::Markup::Attribute.bitmap_for name
219: 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 184
184: def add_word_pair(start, stop, name)
185: raise ArgumentError, "Word flags may not start with '<'" if
186: start[0,1] == '<'
187:
188: bitmap = RDoc::Markup::Attribute.bitmap_for name
189:
190: if start == stop then
191: @matching_word_pairs[start] = bitmap
192: else
193: pattern = /(#{Regexp.escape start})(\S+)(#{Regexp.escape stop})/
194: @word_pair_map[pattern] = bitmap
195: end
196:
197: @protectable << start[0,1]
198: @protectable.uniq!
199: end
Return an attribute object with the given turn_on and turn_off bits set
# File lib/rdoc/markup/attribute_manager.rb, line 78
78: def attribute(turn_on, turn_off)
79: RDoc::Markup::AttrChanger.new turn_on, turn_off
80: end
# File lib/rdoc/markup/attribute_manager.rb, line 82
82: def change_attribute(current, new)
83: diff = current ^ new
84: attribute(new & diff, current & diff)
85: end
# File lib/rdoc/markup/attribute_manager.rb, line 87
87: def changed_attribute_by_name(current_set, new_set)
88: current = new = 0
89: current_set.each do |name|
90: current |= RDoc::Markup::Attribute.bitmap_for(name)
91: end
92:
93: new_set.each do |name|
94: new |= RDoc::Markup::Attribute.bitmap_for(name)
95: end
96:
97: change_attribute(current, new)
98: end
Map attributes like textto the sequence 001002
# File lib/rdoc/markup/attribute_manager.rb, line 111
111: def convert_attrs(str, attrs)
112: # first do matching ones
113: tags = @matching_word_pairs.keys.join("")
114:
115: re = /(^|\W)([#{tags}])([#:\\]?[\w.\/-]+?\S?)\22((\W|$)/
116:
117: 1 while str.gsub!(re) do
118: attr = @matching_word_pairs[$2]
119: attrs.set_attrs($`.length + $1.length + $2.length, $3.length, attr)
120: $1 + NULL * $2.length + $3 + NULL * $2.length + $4
121: end
122:
123: # then non-matching
124: unless @word_pair_map.empty? then
125: @word_pair_map.each do |regexp, attr|
126: str.gsub!(regexp) {
127: attrs.set_attrs($`.length + $1.length, $2.length, attr)
128: NULL * $1.length + $2 + NULL * $3.length
129: }
130: end
131: end
132: end
Converts HTML tags to RDoc attributes
# File lib/rdoc/markup/attribute_manager.rb, line 137
137: def convert_html(str, attrs)
138: tags = @html_tags.keys.join '|'
139:
140: 1 while str.gsub!(/<(#{tags})>(.*?)<\/\11>>/) {
141: attr = @html_tags[$1.downcase]
142: html_length = $1.length + 2
143: seq = NULL * html_length
144: attrs.set_attrs($`.length + html_length, $2.length, attr)
145: seq + $2 + seq + NULL
146: }
147: end
Converts special sequences to RDoc attributes
# File lib/rdoc/markup/attribute_manager.rb, line 152
152: def convert_specials(str, attrs)
153: unless @special.empty?
154: @special.each do |regexp, attr|
155: str.scan(regexp) do
156: attrs.set_attrs($`.length, $&.length,
157: attr | RDoc::Markup::Attribute::SPECIAL)
158: end
159: end
160: end
161: end
# File lib/rdoc/markup/attribute_manager.rb, line 100
100: def copy_string(start_pos, end_pos)
101: res = @str[start_pos...end_pos]
102: res.gsub!(/\0000/, '')
103: res
104: end
Debug method that prints a string along with its attributes
# File lib/rdoc/markup/attribute_manager.rb, line 243
243: def display_attributes
244: puts
245: puts @str.tr(NULL, "!")
246: bit = 1
247: 16.times do |bno|
248: line = ""
249: @str.length.times do |i|
250: if (@attrs[i] & bit) == 0
251: line << " "
252: else
253: if bno.zero?
254: line << "S"
255: else
256: line << ("%d" % (bno+1))
257: end
258: end
259: end
260: puts(line) unless line =~ /^ *$/
261: bit <<= 1
262: end
263: end
Processes str converting attributes, HTML and specials
# File lib/rdoc/markup/attribute_manager.rb, line 224
224: def flow(str)
225: @str = str
226:
227: mask_protected_sequences
228:
229: @attrs = RDoc::Markup::AttrSpan.new @str.length
230:
231: convert_attrs @str, @attrs
232: convert_html @str, @attrs
233: convert_specials @str, @attrs
234:
235: unmask_protected_sequences
236:
237: split_into_flow
238: end
Escapes special sequences of text to prevent conversion to RDoc
# File lib/rdoc/markup/attribute_manager.rb, line 166
166: def mask_protected_sequences
167: @str.gsub!(/\\([#{Regexp.escape @protectable.join('')}])/,
168: "\\1#{PROTECT_ATTR}")
169: end
# File lib/rdoc/markup/attribute_manager.rb, line 265
265: def split_into_flow
266: res = []
267: current_attr = 0
268: str = ""
269:
270: str_len = @str.length
271:
272: # skip leading invisible text
273: i = 0
274: i += 1 while i < str_len and @str[i].chr == "\00""
275: start_pos = i
276:
277: # then scan the string, chunking it on attribute changes
278: while i < str_len
279: new_attr = @attrs[i]
280: if new_attr != current_attr
281: if i > start_pos
282: res << copy_string(start_pos, i)
283: start_pos = i
284: end
285:
286: res << change_attribute(current_attr, new_attr)
287: current_attr = new_attr
288:
289: if (current_attr & RDoc::Markup::Attribute::SPECIAL) != 0 then
290: i += 1 while
291: i < str_len and (@attrs[i] & RDoc::Markup::Attribute::SPECIAL) != 0
292:
293: res << RDoc::Markup::Special.new(current_attr,
294: copy_string(start_pos, i))
295: start_pos = i
296: next
297: end
298: end
299:
300: # move on, skipping any invisible characters
301: begin
302: i += 1
303: end while i < str_len and @str[i].chr == "\00""
304: end
305:
306: # tidy up trailing text
307: if start_pos < str_len
308: res << copy_string(start_pos, str_len)
309: end
310:
311: # and reset to all attributes off
312: res << change_attribute(current_attr, 0) if current_attr != 0
313:
314: res
315: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.