class RDoc::Markup::ToRdoc

Outputs RDoc markup as RDoc markup! (mostly)

Constants

DEFAULT_HEADINGS

Attributes

Current indent amount for output in characters

Stack of current list indexes for alphabetic and numeric lists

Stack of list types

Stack of list widths for indentation

Prefix for the next list item. See use_prefix

Output accumulator

Output width in characters

Public Class Methods

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

Calls superclass method RDoc::Markup::Formatter::new
# 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

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

Public Instance Methods

Adds blank_line to the output

# File lib/rdoc/markup/to_rdoc.rb, line 68
def accept_blank_line(blank_line)
  @res << "\n"
end

Adds paragraph to the output

# File lib/rdoc/markup/to_rdoc.rb, line 75
def accept_block_quote(block_quote)
  @indent += 2

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

    part.accept self
  end

  @indent -= 2
end

Adds heading to the output

# File lib/rdoc/markup/to_rdoc.rb, line 90
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

Adds paragraph to the output

# File lib/rdoc/markup/to_rdoc.rb, line 202
def accept_indented_paragraph(paragraph)
  @indent += paragraph.indent
  text = paragraph.text @hard_break
  wrap attributes text
  @indent -= paragraph.indent
end

Finishes consumption of list

# File lib/rdoc/markup/to_rdoc.rb, line 101
def accept_list_end(list)
  @list_index.pop
  @list_type.pop
  @list_width.pop
end

Finishes consumption of list_item

# File lib/rdoc/markup/to_rdoc.rb, line 110
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

Prepares the visitor for consuming list_item

# File lib/rdoc/markup/to_rdoc.rb, line 134
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

Prepares the visitor for consuming list

# File lib/rdoc/markup/to_rdoc.rb, line 167
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

Adds paragraph to the output

# File lib/rdoc/markup/to_rdoc.rb, line 194
def accept_paragraph(paragraph)
  text = paragraph.text @hard_break
  wrap attributes text
end

Adds raw to the output

# File lib/rdoc/markup/to_rdoc.rb, line 212
def accept_raw(raw)
  @res << raw.parts.join("\n")
end

Adds rule to the output

# File lib/rdoc/markup/to_rdoc.rb, line 219
def accept_rule(rule)
  use_prefix or @res << ' ' * @indent
  @res << '-' * (@width - @indent)
  @res << "\n"
end

Adds table to the output

# File lib/rdoc/markup/to_rdoc.rb, line 242
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.compact.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 << widths.zip(aligns).each_with_index.map do |(w, a), i|
      t = row[i] || ""
      extra_width = t.size - calculate_text_width(t)
      t.__send__(a, w + extra_width)
    end.join("|").rstrip << "\n"
  end
end

Outputs verbatim indented 2 columns

# File lib/rdoc/markup/to_rdoc.rb, line 228
def accept_verbatim(verbatim)
  indent = ' ' * (@indent + 2)

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

  @res << "\n"
end
# File lib/rdoc/markup/to_rdoc.rb, line 347
def add_text(text)
  emit_inline(text)
end

Applies attribute-specific markup to text using RDoc::Markup::InlineParser

# File lib/rdoc/markup/to_rdoc.rb, line 358
def attributes(text)
  handle_inline(text)
end
# File lib/rdoc/markup/to_rdoc.rb, line 272
def calculate_text_width(text)
  text.size
end
# File lib/rdoc/markup/to_rdoc.rb, line 351
def emit_inline(text)
  @inline_output << text
end

Returns the generated output

# File lib/rdoc/markup/to_rdoc.rb, line 365
def end_accepting
  @res.join
end
Calls superclass method RDoc::Markup::Formatter#handle_BOLD
# File lib/rdoc/markup/to_rdoc.rb, line 284
def handle_BOLD(target)
  on(:BOLD)
  super
  off(:BOLD)
end
# File lib/rdoc/markup/to_rdoc.rb, line 296
def handle_BOLD_WORD(word)
  on(:BOLD)
  super
  off(:BOLD)
end
Calls superclass method RDoc::Markup::Formatter#handle_EM
# File lib/rdoc/markup/to_rdoc.rb, line 290
def handle_EM(target)
  on(:EM)
  super
  off(:EM)
end
Calls superclass method RDoc::Markup::Formatter#handle_EM_WORD
# File lib/rdoc/markup/to_rdoc.rb, line 302
def handle_EM_WORD(word)
  on(:EM)
  super
  off(:EM)
end
# File lib/rdoc/markup/to_rdoc.rb, line 320
def handle_HARD_BREAK
  add_text("\n")
end
# File lib/rdoc/markup/to_rdoc.rb, line 276
def handle_PLAIN_TEXT(text)
  add_text(text)
end
# File lib/rdoc/markup/to_rdoc.rb, line 280
def handle_REGEXP_HANDLING_TEXT(text)
  add_text(text)
end
Calls superclass method RDoc::Markup::Formatter#handle_STRIKE
# File lib/rdoc/markup/to_rdoc.rb, line 314
def handle_STRIKE(target)
  on(:STRIKE)
  super
  off(:STRIKE)
end
Calls superclass method RDoc::Markup::Formatter#handle_TT
# File lib/rdoc/markup/to_rdoc.rb, line 308
def handle_TT(code)
  on(:TT)
  super
  off(:TT)
end
Calls superclass method RDoc::Markup::Formatter#handle_inline
# File lib/rdoc/markup/to_rdoc.rb, line 329
def handle_inline(text, initial_attributes = [])
  @attributes = Hash.new(0)
  initial_attributes.each { |attr| on(attr) }
  out = @inline_output = +''
  super(text)
  @inline_output = nil
  out
end

Removes preceding \ from the suppressed crossref target

# File lib/rdoc/markup/to_rdoc.rb, line 372
def handle_regexp_SUPPRESSED_CROSSREF(text)
  text.sub('\\', '')
end
# File lib/rdoc/markup/to_rdoc.rb, line 342
def off(attr)
  @attributes[attr] -= 1
  @attributes.delete(attr) if @attributes[attr] == 0
end
# File lib/rdoc/markup/to_rdoc.rb, line 338
def on(attr)
  @attributes[attr] += 1
end

Prepares the visitor for text generation

# File lib/rdoc/markup/to_rdoc.rb, line 379
def start_accepting
  @res = [""]
  @indent = 0
  @prefix = nil

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

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

# File lib/rdoc/markup/to_rdoc.rb, line 393
def use_prefix
  prefix, @prefix = @prefix, nil
  @res << prefix if prefix

  prefix
end

Wraps text to width

# File lib/rdoc/markup/to_rdoc.rb, line 403
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