Class: RDoc::Markup::ToRdoc

Inherits:
Formatter show all
Defined in:
lib/rdoc/markup/to_rdoc.rb

Overview

Outputs RDoc markup as RDoc markup! (mostly)

Direct Known Subclasses

ToAnsi, ToBs, ToMarkdown

Constant Summary collapse

DEFAULT_HEADINGS =
{
    1 => ['= ',      ''],
    2 => ['== ',     ''],
    3 => ['=== ',    ''],
    4 => ['==== ',   ''],
    5 => ['===== ',  ''],
    6 => ['====== ', '']
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Formatter

#accept_document, #add_regexp_handling_RDOCLINK, #add_regexp_handling_TIDYLINK, #add_tag, #annotate, #convert, #convert_flow, #convert_regexp_handling, #convert_string, #each_attr_tag, gen_relative_url, #ignore, #in_tt?, #off_tags, #on_tags, #parse_url, #tt?, #tt_tag?

Constructor Details

#initialize(markup = nil) ⇒ ToRdoc

Creates a new formatter that will output (mostly) RDoc markup



55
56
57
58
59
60
61
62
63
64
# File 'lib/rdoc/markup/to_rdoc.rb', line 55

def initialize(markup = nil)
  super nil, markup

  @markup.add_regexp_handling(/\\\S/, :SUPPRESSED_CROSSREF)
  @width = 78
  init_tags

  @headings = DEFAULT_HEADINGS.dup
  @hard_break = "\n"
end

Instance Attribute Details

#indentObject

Current indent amount for output in characters



20
21
22
# File 'lib/rdoc/markup/to_rdoc.rb', line 20

def indent
  @indent
end

#list_indexObject (readonly)

Stack of current list indexes for alphabetic and numeric lists



30
31
32
# File 'lib/rdoc/markup/to_rdoc.rb', line 30

def list_index
  @list_index
end

#list_typeObject (readonly)

Stack of list types



35
36
37
# File 'lib/rdoc/markup/to_rdoc.rb', line 35

def list_type
  @list_type
end

#list_widthObject (readonly)

Stack of list widths for indentation



40
41
42
# File 'lib/rdoc/markup/to_rdoc.rb', line 40

def list_width
  @list_width
end

#prefixObject (readonly)

Prefix for the next list item. See #use_prefix



45
46
47
# File 'lib/rdoc/markup/to_rdoc.rb', line 45

def prefix
  @prefix
end

#resObject (readonly)

Output accumulator



50
51
52
# File 'lib/rdoc/markup/to_rdoc.rb', line 50

def res
  @res
end

#widthObject

Output width in characters



25
26
27
# File 'lib/rdoc/markup/to_rdoc.rb', line 25

def width
  @width
end

Instance Method Details

#accept_blank_line(blank_line) ⇒ Object

Adds blank_line to the output



78
79
80
# File 'lib/rdoc/markup/to_rdoc.rb', line 78

def accept_blank_line(blank_line)
  @res << "\n"
end

#accept_block_quote(block_quote) ⇒ Object

Adds paragraph to the output



85
86
87
88
89
90
91
92
93
94
95
# File 'lib/rdoc/markup/to_rdoc.rb', line 85

def accept_block_quote(block_quote)
  @indent += 2

  block_quote.parts.each do |part|
    @prefix = '> '

    part.accept self
  end

  @indent -= 2
end

#accept_heading(heading) ⇒ Object

Adds heading to the output



100
101
102
103
104
105
106
# File 'lib/rdoc/markup/to_rdoc.rb', line 100

def accept_heading(heading)
  use_prefix or @res << ' ' * @indent
  @res << @headings[heading.level][0]
  @res << attributes(heading.text)
  @res << @headings[heading.level][1]
  @res << "\n"
end

#accept_indented_paragraph(paragraph) ⇒ Object

Adds paragraph to the output



212
213
214
215
216
217
# File 'lib/rdoc/markup/to_rdoc.rb', line 212

def accept_indented_paragraph(paragraph)
  @indent += paragraph.indent
  text = paragraph.text @hard_break
  wrap attributes text
  @indent -= paragraph.indent
end

#accept_list_end(list) ⇒ Object

Finishes consumption of list



111
112
113
114
115
# File 'lib/rdoc/markup/to_rdoc.rb', line 111

def accept_list_end(list)
  @list_index.pop
  @list_type.pop
  @list_width.pop
end

#accept_list_item_end(list_item) ⇒ Object

Finishes consumption of list_item



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/rdoc/markup/to_rdoc.rb', line 120

def accept_list_item_end(list_item)
  width = case @list_type.last
          when :BULLET then
            2
          when :NOTE, :LABEL then
            if @prefix then
              @res << @prefix.strip
              @prefix = nil
            end

            @res << "\n"
            2
          else
            bullet = @list_index.last.to_s
            @list_index[-1] = @list_index.last.succ
            bullet.length + 2
          end

  @indent -= width
end

#accept_list_item_start(list_item) ⇒ Object

Prepares the visitor for consuming list_item



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/rdoc/markup/to_rdoc.rb', line 144

def accept_list_item_start(list_item)
  type = @list_type.last

  case type
  when :NOTE, :LABEL then
    stripped_labels = Array(list_item.label).map do |label|
      attributes(label).strip
    end

    bullets = case type
    when :NOTE
      stripped_labels.map { |b| "#{b}::" }
    when :LABEL
      stripped_labels.map { |b| "[#{b}]" }
    end

    bullets = bullets.join("\n")
    bullets << "\n" unless stripped_labels.empty?

    @prefix = ' ' * @indent
    @indent += 2
    @prefix << bullets + (' ' * @indent)
  else
    bullet = type == :BULLET ? '*' :  @list_index.last.to_s + '.'
    @prefix = (' ' * @indent) + bullet.ljust(bullet.length + 1)
    width = bullet.length + 1
    @indent += width
  end
end

#accept_list_start(list) ⇒ Object

Prepares the visitor for consuming list



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/rdoc/markup/to_rdoc.rb', line 177

def accept_list_start(list)
  case list.type
  when :BULLET then
    @list_index << nil
    @list_width << 1
  when :LABEL, :NOTE then
    @list_index << nil
    @list_width << 2
  when :LALPHA then
    @list_index << 'a'
    @list_width << list.items.length.to_s.length
  when :NUMBER then
    @list_index << 1
    @list_width << list.items.length.to_s.length
  when :UALPHA then
    @list_index << 'A'
    @list_width << list.items.length.to_s.length
  else
    raise RDoc::Error, "invalid list type #{list.type}"
  end

  @list_type << list.type
end

#accept_paragraph(paragraph) ⇒ Object

Adds paragraph to the output



204
205
206
207
# File 'lib/rdoc/markup/to_rdoc.rb', line 204

def accept_paragraph(paragraph)
  text = paragraph.text @hard_break
  wrap attributes text
end

#accept_raw(raw) ⇒ Object

Adds raw to the output



222
223
224
# File 'lib/rdoc/markup/to_rdoc.rb', line 222

def accept_raw(raw)
  @res << raw.parts.join("\n")
end

#accept_rule(rule) ⇒ Object

Adds rule to the output



229
230
231
232
233
# File 'lib/rdoc/markup/to_rdoc.rb', line 229

def accept_rule(rule)
  use_prefix or @res << ' ' * @indent
  @res << '-' * (@width - @indent)
  @res << "\n"
end

#accept_table(header, body, aligns) ⇒ Object

Adds table to the output



252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/rdoc/markup/to_rdoc.rb', line 252

def accept_table(header, body, aligns)
  header = header.map { |h| attributes h }
  body = body.map { |row| row.map { |t| attributes t } }
  widths = header.zip(*body).map do |cols|
    cols.map { |col| calculate_text_width(col) }.max
  end
  aligns = aligns.map do |a|
    case a
    when nil, :center
      :center
    when :left
      :ljust
    when :right
      :rjust
    end
  end
  @res << header.zip(widths, aligns).map do |h, w, a|
    extra_width = h.size - calculate_text_width(h)
    h.__send__(a, w + extra_width)
  end.join("|").rstrip << "\n"
  @res << widths.map {|w| "-" * w }.join("|") << "\n"
  body.each do |row|
    @res << row.zip(widths, aligns).map do |t, w, a|
      extra_width = t.size - calculate_text_width(t)
      t.__send__(a, w + extra_width)
    end.join("|").rstrip << "\n"
  end
end

#accept_verbatim(verbatim) ⇒ Object

Outputs verbatim indented 2 columns



238
239
240
241
242
243
244
245
246
247
# File 'lib/rdoc/markup/to_rdoc.rb', line 238

def accept_verbatim(verbatim)
  indent = ' ' * (@indent + 2)

  verbatim.parts.each do |part|
    @res << indent unless part == "\n"
    @res << part
  end

  @res << "\n"
end

#attributes(text) ⇒ Object

Applies attribute-specific markup to text using RDoc::AttributeManager



288
289
290
291
# File 'lib/rdoc/markup/to_rdoc.rb', line 288

def attributes(text)
  flow = @am.flow text.dup
  convert_flow flow
end

#calculate_text_width(text) ⇒ Object



281
282
283
# File 'lib/rdoc/markup/to_rdoc.rb', line 281

def calculate_text_width(text)
  text.size
end

#end_acceptingObject

Returns the generated output



296
297
298
# File 'lib/rdoc/markup/to_rdoc.rb', line 296

def end_accepting
  @res.join
end

#handle_regexp_HARD_BREAK(target) ⇒ Object

Adds a newline to the output



312
313
314
# File 'lib/rdoc/markup/to_rdoc.rb', line 312

def handle_regexp_HARD_BREAK(target)
  "\n"
end

#handle_regexp_SUPPRESSED_CROSSREF(target) ⇒ Object

Removes preceding \ from the suppressed crossref target



303
304
305
306
307
# File 'lib/rdoc/markup/to_rdoc.rb', line 303

def handle_regexp_SUPPRESSED_CROSSREF(target)
  text = target.text
  text = text.sub('\\', '') unless in_tt?
  text
end

#init_tagsObject

Maps attributes to HTML sequences



69
70
71
72
73
# File 'lib/rdoc/markup/to_rdoc.rb', line 69

def init_tags
  add_tag :BOLD, "<b>", "</b>"
  add_tag :TT,   "<tt>", "</tt>"
  add_tag :EM,   "<em>", "</em>"
end

#start_acceptingObject

Prepares the visitor for text generation



319
320
321
322
323
324
325
326
327
# File 'lib/rdoc/markup/to_rdoc.rb', line 319

def start_accepting
  @res = [""]
  @indent = 0
  @prefix = nil

  @list_index = []
  @list_type  = []
  @list_width = []
end

#use_prefixObject

Adds the stored #prefix to the output and clears it. Lists generate a prefix for later consumption.



333
334
335
336
337
338
# File 'lib/rdoc/markup/to_rdoc.rb', line 333

def use_prefix
  prefix, @prefix = @prefix, nil
  @res << prefix if prefix

  prefix
end

#wrap(text) ⇒ Object

Wraps text to #width



343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
# File 'lib/rdoc/markup/to_rdoc.rb', line 343

def wrap(text)
  return unless text && !text.empty?

  text_len = @width - @indent

  text_len = 20 if text_len < 20

  next_prefix = ' ' * @indent

  prefix = @prefix || next_prefix
  @prefix = nil

  text.scan(/\G(?:([^ \n]{#{text_len}})(?=[^ \n])|(.{1,#{text_len}})(?:[ \n]|\z))/) do
    @res << prefix << ($1 || $2) << "\n"
    prefix = next_prefix
  end
end