summaryrefslogtreecommitdiff
path: root/trunk/lib/rdoc/ri/formatter.rb
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/lib/rdoc/ri/formatter.rb')
-rw-r--r--trunk/lib/rdoc/ri/formatter.rb616
1 files changed, 0 insertions, 616 deletions
diff --git a/trunk/lib/rdoc/ri/formatter.rb b/trunk/lib/rdoc/ri/formatter.rb
deleted file mode 100644
index 0a0c3f7380..0000000000
--- a/trunk/lib/rdoc/ri/formatter.rb
+++ /dev/null
@@ -1,616 +0,0 @@
-require 'rdoc/ri'
-require 'rdoc/markup'
-
-class RDoc::RI::Formatter
-
- attr_writer :indent
- attr_accessor :output
-
- FORMATTERS = { }
-
- def self.for(name)
- FORMATTERS[name.downcase]
- end
-
- def self.list
- FORMATTERS.keys.sort.join ", "
- end
-
- def initialize(output, width, indent)
- @output = output
- @width = width
- @indent = indent
- @original_indent = indent.dup
- end
-
- def draw_line(label=nil)
- len = @width
- len -= (label.size + 1) if label
-
- if len > 0 then
- @output.print '-' * len
- if label
- @output.print ' '
- bold_print label
- end
-
- @output.puts
- else
- @output.print '-' * @width
- @output.puts
-
- @output.puts label
- end
- end
-
- def indent
- return @indent unless block_given?
-
- begin
- indent = @indent.dup
- @indent += @original_indent
- yield
- ensure
- @indent = indent
- end
- end
-
- def wrap(txt, prefix=@indent, linelen=@width)
- return unless txt && !txt.empty?
-
- work = conv_markup(txt)
- textLen = linelen - prefix.length
- patt = Regexp.new("^(.{0,#{textLen}})[ \n]")
- next_prefix = prefix.tr("^ ", " ")
-
- res = []
-
- while work.length > textLen
- if work =~ patt
- res << $1
- work.slice!(0, $&.length)
- else
- res << work.slice!(0, textLen)
- end
- end
- res << work if work.length.nonzero?
- @output.puts(prefix + res.join("\n" + next_prefix))
- end
-
- def blankline
- @output.puts
- end
-
- ##
- # Called when we want to ensure a new 'wrap' starts on a newline. Only
- # needed for HtmlFormatter, because the rest do their own line breaking.
-
- def break_to_newline
- end
-
- def bold_print(txt)
- @output.print txt
- end
-
- def raw_print_line(txt)
- @output.puts txt
- end
-
- ##
- # Convert HTML entities back to ASCII
-
- def conv_html(txt)
- txt = txt.gsub(/&gt;/, '>')
- txt.gsub!(/&lt;/, '<')
- txt.gsub!(/&quot;/, '"')
- txt.gsub!(/&amp;/, '&')
- txt
- end
-
- ##
- # Convert markup into display form
-
- def conv_markup(txt)
- txt = txt.gsub(%r{<tt>(.*?)</tt>}, '+\1+')
- txt.gsub!(%r{<code>(.*?)</code>}, '+\1+')
- txt.gsub!(%r{<b>(.*?)</b>}, '*\1*')
- txt.gsub!(%r{<em>(.*?)</em>}, '_\1_')
- txt
- end
-
- def display_list(list)
- case list.type
- when :BULLET
- prefixer = proc { |ignored| @indent + "* " }
-
- when :NUMBER, :UPPERALPHA, :LOWERALPHA then
- start = case list.type
- when :NUMBER then 1
- when :UPPERALPHA then 'A'
- when :LOWERALPHA then 'a'
- end
-
- prefixer = proc do |ignored|
- res = @indent + "#{start}.".ljust(4)
- start = start.succ
- res
- end
-
- when :LABELED, :NOTE then
- longest = 0
-
- list.contents.each do |item|
- if RDoc::Markup::Flow::LI === item and item.label.length > longest then
- longest = item.label.length
- end
- end
-
- longest += 1
-
- prefixer = proc { |li| @indent + li.label.ljust(longest) }
-
- else
- raise ArgumentError, "unknown list type #{list.type}"
- end
-
- list.contents.each do |item|
- if RDoc::Markup::Flow::LI === item then
- prefix = prefixer.call item
- display_flow_item item, prefix
- else
- display_flow_item item
- end
- end
- end
-
- def display_flow_item(item, prefix = @indent)
- case item
- when RDoc::Markup::Flow::P, RDoc::Markup::Flow::LI
- wrap(conv_html(item.body), prefix)
- blankline
-
- when RDoc::Markup::Flow::LIST
- display_list(item)
-
- when RDoc::Markup::Flow::VERB
- display_verbatim_flow_item(item, @indent)
-
- when RDoc::Markup::Flow::H
- display_heading(conv_html(item.text), item.level, @indent)
-
- when RDoc::Markup::Flow::RULE
- draw_line
-
- else
- raise RDoc::Error, "Unknown flow element: #{item.class}"
- end
- end
-
- def display_verbatim_flow_item(item, prefix=@indent)
- item.body.split(/\n/).each do |line|
- @output.print @indent, conv_html(line), "\n"
- end
- blankline
- end
-
- def display_heading(text, level, indent)
- text = strip_attributes text
-
- case level
- when 1 then
- ul = "=" * text.length
- @output.puts
- @output.puts text.upcase
- @output.puts ul
-
- when 2 then
- ul = "-" * text.length
- @output.puts
- @output.puts text
- @output.puts ul
- else
- @output.print indent, text, "\n"
- end
-
- @output.puts
- end
-
- def display_flow(flow)
- flow.each do |f|
- display_flow_item(f)
- end
- end
-
- def strip_attributes(text)
- text.gsub(/(<\/?(?:b|code|em|i|tt)>)/, '')
- end
-
-end
-
-##
-# Handle text with attributes. We're a base class: there are different
-# presentation classes (one, for example, uses overstrikes to handle bold and
-# underlining, while another using ANSI escape sequences.
-
-class RDoc::RI::AttributeFormatter < RDoc::RI::Formatter
-
- BOLD = 1
- ITALIC = 2
- CODE = 4
-
- ATTR_MAP = {
- "b" => BOLD,
- "code" => CODE,
- "em" => ITALIC,
- "i" => ITALIC,
- "tt" => CODE
- }
-
- AttrChar = Struct.new :char, :attr
-
- class AttributeString
- attr_reader :txt
-
- def initialize
- @txt = []
- @optr = 0
- end
-
- def <<(char)
- @txt << char
- end
-
- def empty?
- @optr >= @txt.length
- end
-
- # accept non space, then all following spaces
- def next_word
- start = @optr
- len = @txt.length
-
- while @optr < len && @txt[@optr].char != " "
- @optr += 1
- end
-
- while @optr < len && @txt[@optr].char == " "
- @optr += 1
- end
-
- @txt[start...@optr]
- end
- end
-
- ##
- # Overrides base class. Looks for <tt>...</tt> etc sequences and generates
- # an array of AttrChars. This array is then used as the basis for the
- # split.
-
- def wrap(txt, prefix=@indent, linelen=@width)
- return unless txt && !txt.empty?
-
- txt = add_attributes_to(txt)
- next_prefix = prefix.tr("^ ", " ")
- linelen -= prefix.size
-
- line = []
-
- until txt.empty?
- word = txt.next_word
- if word.size + line.size > linelen
- write_attribute_text(prefix, line)
- prefix = next_prefix
- line = []
- end
- line.concat(word)
- end
-
- write_attribute_text(prefix, line) if line.length > 0
- end
-
- protected
-
- def write_attribute_text(prefix, line)
- @output.print prefix
- line.each do |achar|
- @output.print achar.char
- end
- @output.puts
- end
-
- def bold_print(txt)
- @output.print txt
- end
-
- private
-
- def add_attributes_to(txt)
- tokens = txt.split(%r{(</?(?:b|code|em|i|tt)>)})
- text = AttributeString.new
- attributes = 0
- tokens.each do |tok|
- case tok
- when %r{^</(\w+)>$} then attributes &= ~(ATTR_MAP[$1]||0)
- when %r{^<(\w+)>$} then attributes |= (ATTR_MAP[$1]||0)
- else
- tok.split(//).each {|ch| text << AttrChar.new(ch, attributes)}
- end
- end
- text
- end
-
-end
-
-##
-# This formatter generates overstrike-style formatting, which works with
-# pagers such as man and less.
-
-class RDoc::RI::OverstrikeFormatter < RDoc::RI::AttributeFormatter
-
- BS = "\C-h"
-
- def write_attribute_text(prefix, line)
- @output.print prefix
-
- line.each do |achar|
- attr = achar.attr
- @output.print "_", BS if (attr & (ITALIC + CODE)) != 0
- @output.print achar.char, BS if (attr & BOLD) != 0
- @output.print achar.char
- end
-
- @output.puts
- end
-
- ##
- # Draw a string in bold
-
- def bold_print(text)
- text.split(//).each do |ch|
- @output.print ch, BS, ch
- end
- end
-
-end
-
-##
-# This formatter uses ANSI escape sequences to colorize stuff works with
-# pagers such as man and less.
-
-class RDoc::RI::AnsiFormatter < RDoc::RI::AttributeFormatter
-
- def initialize(*args)
- super
- @output.print "\033[0m"
- end
-
- def write_attribute_text(prefix, line)
- @output.print prefix
- curr_attr = 0
- line.each do |achar|
- attr = achar.attr
- if achar.attr != curr_attr
- update_attributes(achar.attr)
- curr_attr = achar.attr
- end
- @output.print achar.char
- end
- update_attributes(0) unless curr_attr.zero?
- @output.puts
- end
-
- def bold_print(txt)
- @output.print "\033[1m#{txt}\033[m"
- end
-
- HEADINGS = {
- 1 => ["\033[1;32m", "\033[m"],
- 2 => ["\033[4;32m", "\033[m"],
- 3 => ["\033[32m", "\033[m"],
- }
-
- def display_heading(text, level, indent)
- level = 3 if level > 3
- heading = HEADINGS[level]
- @output.print indent
- @output.print heading[0]
- @output.print strip_attributes(text)
- @output.puts heading[1]
- end
-
- private
-
- ATTR_MAP = {
- BOLD => "1",
- ITALIC => "33",
- CODE => "36"
- }
-
- def update_attributes(attr)
- str = "\033["
- for quality in [ BOLD, ITALIC, CODE]
- unless (attr & quality).zero?
- str << ATTR_MAP[quality]
- end
- end
- @output.print str, "m"
- end
-
-end
-
-##
-# This formatter uses HTML.
-
-class RDoc::RI::HtmlFormatter < RDoc::RI::AttributeFormatter
-
- def write_attribute_text(prefix, line)
- curr_attr = 0
- line.each do |achar|
- attr = achar.attr
- if achar.attr != curr_attr
- update_attributes(curr_attr, achar.attr)
- curr_attr = achar.attr
- end
- @output.print(escape(achar.char))
- end
- update_attributes(curr_attr, 0) unless curr_attr.zero?
- end
-
- def draw_line(label=nil)
- if label != nil
- bold_print(label)
- end
- @output.puts("<hr>")
- end
-
- def bold_print(txt)
- tag("b") { txt }
- end
-
- def blankline()
- @output.puts("<p>")
- end
-
- def break_to_newline
- @output.puts("<br>")
- end
-
- def display_heading(text, level, indent)
- level = 4 if level > 4
- tag("h#{level}") { text }
- @output.puts
- end
-
- def display_list(list)
- case list.type
- when :BULLET then
- list_type = "ul"
- prefixer = proc { |ignored| "<li>" }
-
- when :NUMBER, :UPPERALPHA, :LOWERALPHA then
- list_type = "ol"
- prefixer = proc { |ignored| "<li>" }
-
- when :LABELED then
- list_type = "dl"
- prefixer = proc do |li|
- "<dt><b>" + escape(li.label) + "</b><dd>"
- end
-
- when :NOTE then
- list_type = "table"
- prefixer = proc do |li|
- %{<tr valign="top"><td>#{li.label.gsub(/ /, '&nbsp;')}</td><td>}
- end
- else
- fail "unknown list type"
- end
-
- @output.print "<#{list_type}>"
- list.contents.each do |item|
- if item.kind_of? RDoc::Markup::Flow::LI
- prefix = prefixer.call(item)
- @output.print prefix
- display_flow_item(item, prefix)
- else
- display_flow_item(item)
- end
- end
- @output.print "</#{list_type}>"
- end
-
- def display_verbatim_flow_item(item, prefix=@indent)
- @output.print("<pre>")
- item.body.split(/\n/).each do |line|
- @output.puts conv_html(line)
- end
- @output.puts("</pre>")
- end
-
- private
-
- ATTR_MAP = {
- BOLD => "b>",
- ITALIC => "i>",
- CODE => "tt>"
- }
-
- def update_attributes(current, wanted)
- str = ""
- # first turn off unwanted ones
- off = current & ~wanted
- for quality in [ BOLD, ITALIC, CODE]
- if (off & quality) > 0
- str << "</" + ATTR_MAP[quality]
- end
- end
-
- # now turn on wanted
- for quality in [ BOLD, ITALIC, CODE]
- unless (wanted & quality).zero?
- str << "<" << ATTR_MAP[quality]
- end
- end
- @output.print str
- end
-
- def tag(code)
- @output.print("<#{code}>")
- @output.print(yield)
- @output.print("</#{code}>")
- end
-
- def escape(str)
- str = str.gsub(/&/n, '&amp;')
- str.gsub!(/\"/n, '&quot;')
- str.gsub!(/>/n, '&gt;')
- str.gsub!(/</n, '&lt;')
- str
- end
-
-end
-
-##
-# This formatter reduces extra lines for a simpler output. It improves way
-# output looks for tools like IRC bots.
-
-class RDoc::RI::SimpleFormatter < RDoc::RI::Formatter
-
- ##
- # No extra blank lines
-
- def blankline
- end
-
- ##
- # Display labels only, no lines
-
- def draw_line(label=nil)
- unless label.nil? then
- bold_print(label)
- @output.puts
- end
- end
-
- ##
- # Place heading level indicators inline with heading.
-
- def display_heading(text, level, indent)
- text = strip_attributes(text)
- case level
- when 1
- @output.puts "= " + text.upcase
- when 2
- @output.puts "-- " + text
- else
- @output.print indent, text, "\n"
- end
- end
-
-end
-
-RDoc::RI::Formatter::FORMATTERS['plain'] = RDoc::RI::Formatter
-RDoc::RI::Formatter::FORMATTERS['simple'] = RDoc::RI::SimpleFormatter
-RDoc::RI::Formatter::FORMATTERS['bs'] = RDoc::RI::OverstrikeFormatter
-RDoc::RI::Formatter::FORMATTERS['ansi'] = RDoc::RI::AnsiFormatter
-RDoc::RI::Formatter::FORMATTERS['html'] = RDoc::RI::HtmlFormatter