Class RDoc::Markup::AttributeManager
In: markup/inline.rb
Parent: Object

Methods

Public Class methods

[Source]

     # 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

Public Instance methods

[Source]

     # File markup/inline.rb, line 256
256:     def add_html(tag, name)
257:       HTML_TAGS[tag.downcase] = Attribute.bitmap_for(name)
258:     end

[Source]

     # File markup/inline.rb, line 260
260:     def add_special(pattern, name)
261:       SPECIAL[pattern] = Attribute.bitmap_for(name)
262:     end

[Source]

     # 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

Return an attribute object with the given turn_on and turn_off bits set

[Source]

     # File markup/inline.rb, line 139
139:     def attribute(turn_on, turn_off)
140:       AttrChanger.new(turn_on, turn_off)
141:     end

[Source]

     # File markup/inline.rb, line 143
143:     def change_attribute(current, new)
144:       diff = current ^ new
145:       attribute(new & diff, current & diff)
146:     end

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # File markup/inline.rb, line 222
222:     def unmask_protected_sequences
223:       @str.gsub!(/(.)#{PROTECT_ATTR}/, "\\1\000")
224:     end

[Validate]