| Class | RDoc::Markup::AttributeManager |
| In: |
markup/inline.rb
|
| Parent: | Object |
# File markup/inline.rb, line 226
226: def initialize
227: add_word_pair("*", "*", :BOLD)
228: add_word_pair("_", "_", :EM)
229: add_word_pair("+", "+", :TT)
230:
231: add_html("em", :EM)
232: add_html("i", :EM)
233: add_html("b", :BOLD)
234: add_html("tt", :TT)
235: add_html("code", :TT)
236:
237: add_special(/<!--(.*?)-->/, :COMMENT)
238: end
# File markup/inline.rb, line 256
256: def add_html(tag, name)
257: HTML_TAGS[tag.downcase] = Attribute.bitmap_for(name)
258: end
# File markup/inline.rb, line 260
260: def add_special(pattern, name)
261: SPECIAL[pattern] = Attribute.bitmap_for(name)
262: end
# File markup/inline.rb, line 240
240: def add_word_pair(start, stop, name)
241: raise "Word flags may not start '<'" if start[0] == ?<
242: bitmap = Attribute.bitmap_for(name)
243: if start == stop
244: MATCHING_WORD_PAIRS[start] = bitmap
245: else
246: pattern = Regexp.new("(" + Regexp.escape(start) + ")" +
247: # "([A-Za-z]+)" +
248: "(\\S+)" +
249: "(" + Regexp.escape(stop) +")")
250: WORD_PAIR_MAP[pattern] = bitmap
251: end
252: PROTECTABLE << start[0,1]
253: PROTECTABLE.uniq!
254: end
# File markup/inline.rb, line 143
143: def change_attribute(current, new)
144: diff = current ^ new
145: attribute(new & diff, current & diff)
146: end
# File markup/inline.rb, line 148
148: def changed_attribute_by_name(current_set, new_set)
149: current = new = 0
150: current_set.each {|name| current |= Attribute.bitmap_for(name) }
151: new_set.each {|name| new |= Attribute.bitmap_for(name) }
152: change_attribute(current, new)
153: end
Map attributes like textto the sequence 001\002<char>001\003<char>, where <char> is a per-attribute specific character
# File markup/inline.rb, line 166
166: def convert_attrs(str, attrs)
167: # first do matching ones
168: tags = MATCHING_WORD_PAIRS.keys.join("")
169:
170: re = /(^|\W)([#{tags}])([#\\]?[\w.\/]+?\S?)\2(\W|$)/
171:
172: 1 while str.gsub!(re) do
173: attr = MATCHING_WORD_PAIRS[$2]
174: attrs.set_attrs($`.length + $1.length + $2.length, $3.length, attr)
175: $1 + NULL * $2.length + $3 + NULL * $2.length + $4
176: end
177:
178: # then non-matching
179: unless WORD_PAIR_MAP.empty? then
180: WORD_PAIR_MAP.each do |regexp, attr|
181: str.gsub!(regexp) {
182: attrs.set_attrs($`.length + $1.length, $2.length, attr)
183: NULL * $1.length + $2 + NULL * $3.length
184: }
185: end
186: end
187: end
# File markup/inline.rb, line 189
189: def convert_html(str, attrs)
190: tags = HTML_TAGS.keys.join '|'
191:
192: 1 while str.gsub!(/<(#{tags})>(.*?)<\/\1>/i) {
193: attr = HTML_TAGS[$1.downcase]
194: html_length = $1.length + 2
195: seq = NULL * html_length
196: attrs.set_attrs($`.length + html_length, $2.length, attr)
197: seq + $2 + seq + NULL
198: }
199: end
# File markup/inline.rb, line 201
201: def convert_specials(str, attrs)
202: unless SPECIAL.empty?
203: SPECIAL.each do |regexp, attr|
204: str.scan(regexp) do
205: attrs.set_attrs($`.length, $&.length, attr | Attribute::SPECIAL)
206: end
207: end
208: end
209: end
# File markup/inline.rb, line 155
155: def copy_string(start_pos, end_pos)
156: res = @str[start_pos...end_pos]
157: res.gsub!(/\000/, '')
158: res
159: end
# File markup/inline.rb, line 285
285: def display_attributes
286: puts
287: puts @str.tr(NULL, "!")
288: bit = 1
289: 16.times do |bno|
290: line = ""
291: @str.length.times do |i|
292: if (@attrs[i] & bit) == 0
293: line << " "
294: else
295: if bno.zero?
296: line << "S"
297: else
298: line << ("%d" % (bno+1))
299: end
300: end
301: end
302: puts(line) unless line =~ /^ *$/
303: bit <<= 1
304: end
305: end
# File markup/inline.rb, line 264
264: def flow(str)
265: @str = str
266:
267: puts("Before flow, str='#{@str.dump}'") if $DEBUG_RDOC
268: mask_protected_sequences
269:
270: @attrs = AttrSpan.new(@str.length)
271:
272: puts("After protecting, str='#{@str.dump}'") if $DEBUG_RDOC
273:
274: convert_attrs(@str, @attrs)
275: convert_html(@str, @attrs)
276: convert_specials(str, @attrs)
277:
278: unmask_protected_sequences
279:
280: puts("After flow, str='#{@str.dump}'") if $DEBUG_RDOC
281:
282: return split_into_flow
283: end
# File markup/inline.rb, line 217
217: def mask_protected_sequences
218: protect_pattern = Regexp.new("\\\\([#{Regexp.escape(PROTECTABLE.join(''))}])")
219: @str.gsub!(protect_pattern, "\\1#{PROTECT_ATTR}")
220: end
# File markup/inline.rb, line 307
307: def split_into_flow
308: display_attributes if $DEBUG_RDOC
309:
310: res = []
311: current_attr = 0
312: str = ""
313:
314: str_len = @str.length
315:
316: # skip leading invisible text
317: i = 0
318: i += 1 while i < str_len and @str[i] == "\0"
319: start_pos = i
320:
321: # then scan the string, chunking it on attribute changes
322: while i < str_len
323: new_attr = @attrs[i]
324: if new_attr != current_attr
325: if i > start_pos
326: res << copy_string(start_pos, i)
327: start_pos = i
328: end
329:
330: res << change_attribute(current_attr, new_attr)
331: current_attr = new_attr
332:
333: if (current_attr & Attribute::SPECIAL) != 0
334: i += 1 while i < str_len and (@attrs[i] & Attribute::SPECIAL) != 0
335: res << Special.new(current_attr, copy_string(start_pos, i))
336: start_pos = i
337: next
338: end
339: end
340:
341: # move on, skipping any invisible characters
342: begin
343: i += 1
344: end while i < str_len and @str[i] == "\0"
345: end
346:
347: # tidy up trailing text
348: if start_pos < str_len
349: res << copy_string(start_pos, str_len)
350: end
351:
352: # and reset to all attributes off
353: res << change_attribute(current_attr, 0) if current_attr != 0
354:
355: return res
356: end