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 57
def initialize
  super

  @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 70
def accept_blank_line(blank_line)
  @res << "\n"
end

Adds paragraph to the output

# File lib/rdoc/markup/to_rdoc.rb, line 77
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 92
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 204
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 103
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 112
def accept_list_item_end(list_item)
  width = case @list_type.last
          when :BULLET
            2
          when :NOTE, :LABEL
            if @prefix
              @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 136
def accept_list_item_start(list_item)
  type = @list_type.last

  case type
  when :NOTE, :LABEL
    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 169
def accept_list_start(list)
  case list.type
  when :BULLET
    @list_index << nil
    @list_width << 1
  when :LABEL, :NOTE
    @list_index << nil
    @list_width << 2
  when :LALPHA
    @list_index << 'a'
    @list_width << list.items.length.to_s.length
  when :NUMBER
    @list_index << 1
    @list_width << list.items.length.to_s.length
  when :UALPHA
    @list_index << 'A'
    @list_width << list.items.length.to_s.length
  else
    raise 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 196
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 214
def accept_raw(raw)
  @res << raw.parts.join("\n")
end

Adds rule to the output

# File lib/rdoc/markup/to_rdoc.rb, line 221
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 244
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 230
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 349
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 360
def attributes(text)
  handle_inline(text)
end
# File lib/rdoc/markup/to_rdoc.rb, line 274
def calculate_text_width(text)
  text.size
end
# File lib/rdoc/markup/to_rdoc.rb, line 353
def emit_inline(text)
  @inline_output << text
end

Returns the generated output

# File lib/rdoc/markup/to_rdoc.rb, line 367
def end_accepting
  @res.join
end
Calls superclass method RDoc::Markup::Formatter#handle_BOLD
# File lib/rdoc/markup/to_rdoc.rb, line 286
def handle_BOLD(target)
  on(:BOLD)
  super
  off(:BOLD)
end
# File lib/rdoc/markup/to_rdoc.rb, line 298
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 292
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 304
def handle_EM_WORD(word)
  on(:EM)
  super
  off(:EM)
end
# File lib/rdoc/markup/to_rdoc.rb, line 322
def handle_HARD_BREAK
  add_text("\n")
end
# File lib/rdoc/markup/to_rdoc.rb, line 278
def handle_PLAIN_TEXT(text)
  add_text(text)
end
# File lib/rdoc/markup/to_rdoc.rb, line 282
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 316
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 310
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 331
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 374
def handle_regexp_SUPPRESSED_CROSSREF(text)
  text.sub('\\', '')
end
# File lib/rdoc/markup/to_rdoc.rb, line 344
def off(attr)
  @attributes[attr] -= 1
  @attributes.delete(attr) if @attributes[attr] == 0
end
# File lib/rdoc/markup/to_rdoc.rb, line 340
def on(attr)
  @attributes[attr] += 1
end

Prepares the visitor for text generation

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