Cleanup RDoc

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@15019 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
drbrain 2008-01-13 03:35:34 +00:00
parent ec519b9b43
commit 0feac89d2d
8 changed files with 201 additions and 211 deletions

View File

@ -1,5 +1,7 @@
# = Introduction
#
require 'rdoc/markup/simple_markup/fragments'
require 'rdoc/markup/simple_markup/lines.rb'
##
# SimpleMarkup parses plain text documents and attempts to decompose
# them into their constituent parts. Some of these parts are high-level:
# paragraphs, chunks of verbatim text, list entries and the like. Other
@ -65,7 +67,7 @@
#
# ant:: a little insect that is known
# to enjoy picnics
#
#
# This latter style guarantees that the list bodies' left margins are
# aligned: think of them as a two column table.
#
@ -107,19 +109,13 @@
#
# = Using SimpleMarkup
#
# For information on using SimpleMarkup programatically,
# see SM::SimpleMarkup.
#
# For information on using SimpleMarkup programatically, see SM::SimpleMarkup.
#--
# Author:: Dave Thomas, dave@pragmaticprogrammer.com
# Version:: 0.0
# License:: Ruby license
require 'rdoc/markup/simple_markup/fragments'
require 'rdoc/markup/simple_markup/lines.rb'
module SM #:nodoc:
module SM
# == Synopsis
#
@ -162,25 +158,18 @@ module SM #:nodoc:
# h.add_tag(:STRIKE, "<strike>", "</strike>")
#
# puts "<body>" + p.convert(ARGF.read, h) + "</body>"
#
# == Output Formatters
#
# _missing_
#
#
class SimpleMarkup
SPACE = ?\s
# List entries look like:
# * text
# 1. text
# [label] text
# label:: text
# * text
# 1. text
# [label] text
# label:: text
#
# Flag it as a list entry, and
# work out the indent for subsequent lines
# Flag it as a list entry, and work out the indent for subsequent lines
SIMPLE_LIST_RE = /^(
( \* (?# bullet)
@ -197,12 +186,10 @@ module SM #:nodoc:
)(?:\s+|$)
)/x
##
# take a block of text and use various heuristics to determine
# it's structure (paragraphs, lists, and so on). Invoke an
# event handler as we identify significant chunks.
#
# Take a block of text and use various heuristics to determine it's
# structure (paragraphs, lists, and so on). Invoke an event handler as we
# identify significant chunks.
def initialize
@am = AttributeManager.new
@ -210,41 +197,39 @@ module SM #:nodoc:
end
##
# Add to the sequences used to add formatting to an individual word
# (such as *bold*). Matching entries will generate attibutes
# that the output formatters can recognize by their +name+
# Add to the sequences used to add formatting to an individual word (such
# as *bold*). Matching entries will generate attibutes that the output
# formatters can recognize by their +name+.
def add_word_pair(start, stop, name)
@am.add_word_pair(start, stop, name)
end
##
# Add to the sequences recognized as general markup
#
# Add to the sequences recognized as general markup.
def add_html(tag, name)
@am.add_html(tag, name)
end
##
# Add to other inline sequences. For example, we could add
# WikiWords using something like:
# Add to other inline sequences. For example, we could add WikiWords using
# something like:
#
# parser.add_special(/\b([A-Z][a-z]+[A-Z]\w+)/, :WIKIWORD)
#
# Each wiki word will be presented to the output formatter
# via the accept_special method
#
# Each wiki word will be presented to the output formatter via the
# accept_special method.
def add_special(pattern, name)
@am.add_special(pattern, name)
end
# We take a string, split it into lines, work out the type of
# each line, and from there deduce groups of lines (for example
# all lines in a paragraph). We then invoke the output formatter
# using a Visitor to display the result
##
# We take a string, split it into lines, work out the type of each line,
# and from there deduce groups of lines (for example all lines in a
# paragraph). We then invoke the output formatter using a Visitor to
# display the result.
def convert(str, op)
@lines = Lines.new(str.split(/\r?\n/).collect { |aLine|
@ -258,16 +243,11 @@ module SM #:nodoc:
group.accept(@am, op)
end
#######
private
#######
##
# Look through the text at line indentation. We flag each line as being
# Blank, a paragraph, a list element, or verbatim text
#
# Blank, a paragraph, a list element, or verbatim text.
def assign_types_to_lines(margin = 0, level = 0)
@ -362,23 +342,24 @@ module SM #:nodoc:
end
end
# Handle labeled list entries, We have a special case
# to deal with. Because the labels can be long, they force
# the remaining block of text over the to right:
##
# Handle labeled list entries, We have a special case to deal with.
# Because the labels can be long, they force the remaining block of text
# over the to right:
#
# this is a long label that I wrote:: and here is the
# block of text with
# a silly margin
# this is a long label that I wrote:: and here is the
# block of text with
# a silly margin
#
# So we allow the special case. If the label is followed
# by nothing, and if the following line is indented, then
# we take the indent of that line as the new margin
# So we allow the special case. If the label is followed by nothing, and
# if the following line is indented, then we take the indent of that line
# as the new margin.
#
# this is a long label that I wrote::
# here is a more reasonably indented block which
# will ab attached to the label.
# this is a long label that I wrote::
# here is a more reasonably indented block which
# will be attached to the label.
#
def handled_labeled_list(line, level, margin, offset, prefix)
prefix_length = prefix.length
text = line.text
@ -425,12 +406,12 @@ module SM #:nodoc:
return true
end
# Return a block consisting of fragments which are
# paragraphs, list entries or verbatim text. We merge consecutive
# lines of the same type and level together. We are also slightly
# tricky with lists: the lines following a list introduction
# look like paragraph lines at the next level, and we remap them
# into list entries instead
##
# Return a block consisting of fragments which are paragraphs, list
# entries or verbatim text. We merge consecutive lines of the same type
# and level together. We are also slightly tricky with lists: the lines
# following a list introduction look like paragraph lines at the next
# level, and we remap them into list entries instead.
def group_lines
@lines.rewind
@ -460,17 +441,23 @@ module SM #:nodoc:
block
end
## for debugging, we allow access to our line contents as text
##
# For debugging, we allow access to our line contents as text.
def content
@lines.as_text
end
public :content
## for debugging, return the list of line types
##
# For debugging, return the list of line types.
def get_line_types
@lines.line_types
end
public :get_line_types
end
end

View File

@ -1,11 +1,10 @@
require 'rdoc/markup/simple_markup/lines.rb'
#require 'rdoc/markup/simple_markup/to_flow.rb'
module SM
##
# A Fragment is a chunk of text, subclassed as a paragraph, a list
# entry, or verbatim text
# entry, or verbatim text.
class Fragment
attr_reader :level, :param, :txt
@ -47,7 +46,7 @@ module SM
##
# A paragraph is a fragment which gets wrapped to fit. We remove all
# newlines when we're created, and have them put back on output
# newlines when we're created, and have them put back on output.
class Paragraph < Fragment
type_name Line::PARAGRAPH
@ -67,7 +66,6 @@ module SM
##
# A List is a fragment with some kind of label
#
class ListBase < Paragraph
# List types
@ -114,16 +112,17 @@ module SM
##
# A horizontal rule
class Rule < Fragment
type_name Line::RULE
end
# Collect groups of lines together. Each group
# will end up containing a flow of text
##
# Collect groups of lines together. Each group will end up containing a flow
# of text
class LineCollection
def initialize
@fragments = []
end
@ -136,17 +135,20 @@ module SM
@fragments.each(&b)
end
# For testing
def to_a
def to_a # :nodoc:
@fragments.map {|fragment| fragment.to_s}
end
##
# Factory for different fragment types
def fragment_for(*args)
Fragment.for(*args)
end
# tidy up at the end
##
# Tidy up at the end
def normalize
change_verbatim_blank_lines
add_list_start_and_ends
@ -159,7 +161,6 @@ module SM
end
def accept(am, visitor)
visitor.start_accepting
@fragments.each do |fragment|
@ -185,9 +186,8 @@ module SM
visitor.end_accepting
end
#######
private
#######
# If you have:
#
@ -197,14 +197,12 @@ module SM
#
# and more code
#
# You'll end up with the fragments Paragraph, BlankLine,
# Verbatim, BlankLine, Verbatim, BlankLine, etc
# You'll end up with the fragments Paragraph, BlankLine, Verbatim,
# BlankLine, Verbatim, BlankLine, etc.
#
# The BlankLine in the middle of the verbatim chunk needs to
# be changed to a real verbatim newline, and the two
# verbatim blocks merged
#
#
# The BlankLine in the middle of the verbatim chunk needs to be changed to
# a real verbatim newline, and the two verbatim blocks merged
def change_verbatim_blank_lines
frag_block = nil
blank_count = 0
@ -232,9 +230,9 @@ module SM
@fragments.compact!
end
# List nesting is implicit given the level of
# Make it explicit, just to make life a tad
# easier for the output processors
##
# List nesting is implicit given the level of indentation. Make it
# explicit, just to make life a tad easier for the output processors
def add_list_start_and_ends
level = 0
@ -270,8 +268,9 @@ module SM
@fragments = res
end
# now insert start/ends between list entries at the
# same level that have different element types
##
# Inserts start/ends between list entries at the same level that have
# different element types
def add_list_breaks
res = @fragments
@ -302,7 +301,8 @@ module SM
end
end
# Finally tidy up the blank lines:
##
# Tidy up the blank lines:
# * change Blank/ListEnd into ListEnd/Blank
# * remove blank lines at the front
@ -324,5 +324,6 @@ module SM
end
end
end

View File

@ -1,7 +1,8 @@
module SM
# We manage a set of attributes. Each attribute has a symbol name
# and a bit value
##
# We manage a set of attributes. Each attribute has a symbol name and a bit
# value
class Attribute
SPECIAL = 1
@ -36,19 +37,21 @@ module SM
end
end
# An AttrChanger records a change in attributes. It contains
# a bitmap of the attributes to turn on, and a bitmap of those to
# turn off
##
# An AttrChanger records a change in attributes. It contains a bitmap of the
# attributes to turn on, and a bitmap of those to turn off
AttrChanger = Struct.new(:turn_on, :turn_off)
class AttrChanger
def to_s
"Attr: +#{Attribute.as_string(@turn_on)}/-#{Attribute.as_string(@turn_on)}"
end
end
##
# An array of attributes which parallels the characters in a string
class AttrSpan
def initialize(length)
@attrs = Array.new(length, 0)
@ -89,46 +92,51 @@ module SM
object_id, @type, SM::Attribute.as_string(type), text.dump]
end
end
class AttributeManager
NULL = "\000".freeze
##
# We work by substituting non-printing characters in to the
# text. For now I'm assuming that I can substitute
# a character in the range 0..8 for a 7 bit character
# without damaging the encoded string, but this might
# be optimistic
#
# We work by substituting non-printing characters in to the text. For now
# I'm assuming that I can substitute a character in the range 0..8 for a 7
# bit character without damaging the encoded string, but this might be
# optimistic
A_PROTECT = 004
PROTECT_ATTR = A_PROTECT.chr
# This maps delimiters that occur around words (such as
# *bold* or +tt+) where the start and end delimiters
# and the same. This lets us optimize the regexp
##
# This maps delimiters that occur around words (such as *bold* or +tt+)
# where the start and end delimiters and the same. This lets us optimize
# the regexp
MATCHING_WORD_PAIRS = {}
# And this is used when the delimiters aren't the same. In this
# case the hash maps a pattern to the attribute character
##
# And this is used when the delimiters aren't the same. In this case the
# hash maps a pattern to the attribute character
WORD_PAIR_MAP = {}
##
# This maps HTML tags to the corresponding attribute char
HTML_TAGS = {}
# And this maps _special_ sequences to a name. A special sequence
# is something like a WikiWord
##
# And this maps _special_ sequences to a name. A special sequence is
# something like a WikiWord
SPECIAL = {}
# Return an attribute object with the given turn_on
# and turn_off bits set
##
# Return an attribute object with the given turn_on and turn_off bits set
def attribute(turn_on, turn_off)
AttrChanger.new(turn_on, turn_off)
end
def change_attribute(current, new)
diff = current ^ new
attribute(new & diff, current & diff)
@ -147,8 +155,10 @@ module SM
res
end
# Map attributes like <b>text</b>to the sequence \001\002<char>\001\003<char>,
# where <char> is a per-attribute specific character
##
# Map attributes like <b>text</b>to the sequence
# \001\002<char>\001\003<char>, where <char> is a per-attribute specific
# character
def convert_attrs(str, attrs)
# first do matching ones
@ -194,10 +204,10 @@ module SM
end
end
# A \ in front of a character that would normally be
# processed turns off processing. We do this by turning
# \< into <#{PROTECT}
##
# A \ in front of a character that would normally be processed turns off
# processing. We do this by turning \< into <#{PROTECT}
PROTECTABLE = [ "<" << "\\" ] #"
@ -214,7 +224,7 @@ module SM
add_word_pair("*", "*", :BOLD)
add_word_pair("_", "_", :EM)
add_word_pair("+", "+", :TT)
add_html("em", :EM)
add_html("i", :EM)
add_html("b", :BOLD)
@ -253,7 +263,7 @@ module SM
puts("Before flow, str='#{@str.dump}'") if $DEBUG_RDOC
mask_protected_sequences
@attrs = AttrSpan.new(@str.length)
puts("After protecting, str='#{@str.dump}'") if $DEBUG_RDOC
@ -295,7 +305,6 @@ module SM
current_attr = 0
str = ""
str_len = @str.length
# skip leading invisible text
@ -328,7 +337,7 @@ module SM
i += 1
end while i < str_len and @str[i] == "\0"
end
# tidy up trailing text
if start_pos < str_len
res << copy_string(start_pos, str_len)
@ -343,3 +352,4 @@ module SM
end
end

View File

@ -1,11 +1,10 @@
##########################################################################
#
# We store the lines we're working on as objects of class Line.
# These contain the text of the line, along with a flag indicating the
# line type, and an indentation level
module SM
##
# We store the lines we're working on as objects of class Line. These
# contain the text of the line, along with a flag indicating the line type,
# and an indentation level.
class Line
INFINITY = 9999
@ -85,15 +84,14 @@ module SM
end
end
###############################################################################
#
##
# A container for all the lines
#
class Lines
include Enumerable
attr_reader :lines # for debugging
attr_reader :lines # :nodoc:
def initialize(lines)
@lines = lines
@ -147,5 +145,8 @@ module SM
def line_types
@lines.map {|l| l.type }
end
end
end

View File

@ -1,10 +1,9 @@
module SM
##
##
# Handle common directives that can occur in a block of text:
#
# : include : filename
#
class PreProcess
@ -13,12 +12,12 @@ module SM
@include_path = include_path
end
# Look for common options in a chunk of text. Options that
# we don't handle are passed back to our caller
# as |directive, param|
##
# Look for common options in a chunk of text. Options that we don't handle
# are passed back to our caller as |directive, param|
def handle(text)
text.gsub!(/^([ \t#]*):(\w+):\s*(.+)?\n/) do
text.gsub!(/^([ \t#]*):(\w+):\s*(.+)?\n/) do
prefix = $1
directive = $2.downcase
param = $3
@ -34,11 +33,10 @@ module SM
end
end
#######
private
#######
# Include a file, indenting it correctly
##
# Include a file, indenting it correctly.
def include_file(name, indent)
if (full_name = find_include_file(name))
@ -55,9 +53,9 @@ module SM
end
end
# Look for the given file in the directory containing the current
# file, and then in each of the directories specified in the
# RDOC_INCLUDE path
##
# Look for the given file in the directory containing the current file,
# and then in each of the directories specified in the RDOC_INCLUDE path
def find_include_file(name)
to_search = [ File.dirname(@input_file_name) ].concat @include_path
@ -70,4 +68,6 @@ module SM
end
end
end

View File

@ -40,7 +40,7 @@ module SM
##
# Set up the standard mapping of attributes to HTML tags
#
def init_tags
@attr_tags = [
InlineTag.new(SM::Attribute.bitmap_for(:BOLD), "<b>", "</b>"),
@ -50,24 +50,23 @@ module SM
end
##
# Add a new set of HTML tags for an attribute. We allow
# separate start and end tags for flexibility
#
# Add a new set of HTML tags for an attribute. We allow separate start and
# end tags for flexibility
def add_tag(name, start, stop)
@attr_tags << InlineTag.new(SM::Attribute.bitmap_for(name), start, stop)
end
##
# Given an HTML tag, decorate it with class information
# and the like if required. This is a no-op in the base
# class, but is overridden in HTML output classes that
# implement style sheets
# Given an HTML tag, decorate it with class information and the like if
# required. This is a no-op in the base class, but is overridden in HTML
# output classes that implement style sheets
def annotate(tag)
tag
end
##
##
# Here's the client side of the visitor pattern
def start_accepting
@ -116,13 +115,8 @@ module SM
@res << Flow::H.new(fragment.head_level, convert_flow(am.flow(fragment.txt)))
end
#######################################################################
private
#######################################################################
def on_tags(res, item)
attr_mask = item.turn_on
return if attr_mask.zero?
@ -163,8 +157,6 @@ module SM
res
end
# some of these patterns are taken from SmartyPants...
def convert_string(item)
CGI.escapeHTML(item)
end
@ -178,11 +170,13 @@ module SM
handled = true
end
end
raise "Unhandled special: #{special}" unless handled
special.text
end
end
end

View File

@ -24,7 +24,7 @@ module SM
##
# Set up the standard mapping of attributes to HTML tags
#
def init_tags
@attr_tags = [
InlineTag.new(SM::Attribute.bitmap_for(:BOLD), "<b>", "</b>"),
@ -34,24 +34,23 @@ module SM
end
##
# Add a new set of HTML tags for an attribute. We allow
# separate start and end tags for flexibility
#
# Add a new set of HTML tags for an attribute. We allow separate start and
# end tags for flexibility.
def add_tag(name, start, stop)
@attr_tags << InlineTag.new(SM::Attribute.bitmap_for(name), start, stop)
end
##
# Given an HTML tag, decorate it with class information
# and the like if required. This is a no-op in the base
# class, but is overridden in HTML output classes that
# implement style sheets
# Given an HTML tag, decorate it with class information and the like if
# required. This is a no-op in the base class, but is overridden in HTML
# output classes that implement style sheets.
def annotate(tag)
tag
end
##
##
# Here's the client side of the visitor pattern
def start_accepting
@ -82,7 +81,7 @@ module SM
end
def accept_list_start(am, fragment)
@res << html_list_name(fragment.type, true) <<"\n"
@res << html_list_name(fragment.type, true) << "\n"
@in_list_entry.push false
end
@ -90,7 +89,7 @@ module SM
if tag = @in_list_entry.pop
@res << annotate(tag) << "\n"
end
@res << html_list_name(fragment.type, false) <<"\n"
@res << html_list_name(fragment.type, false) << "\n"
end
def accept_list_item(am, fragment)
@ -110,6 +109,7 @@ module SM
@res << convert_heading(fragment.head_level, am.flow(fragment.txt))
end
##
# This is a higher speed (if messier) version of wrap
def wrap(txt, line_len = 76)
@ -139,12 +139,8 @@ module SM
res
end
#######################################################################
private
#######################################################################
def on_tags(res, item)
attr_mask = item.turn_on
return if attr_mask.zero?
@ -185,12 +181,12 @@ module SM
res
end
##
# some of these patterns are taken from SmartyPants...
def convert_string(item)
CGI.escapeHTML(item).
# convert -- to em-dash, (-- to en-dash)
gsub(/---?/, '&#8212;'). #gsub(/--/, '&#8211;').
@ -233,8 +229,8 @@ module SM
def convert_heading(level, flow)
res =
annotate("<h#{level}>") +
convert_flow(flow) +
annotate("<h#{level}>") +
convert_flow(flow) +
annotate("</h#{level}>\n")
end
@ -249,21 +245,21 @@ module SM
annotate("<li>")
when ListBase::UPPERALPHA
annotate("<li type=\"A\">")
annotate("<li type=\"A\">")
when ListBase::LOWERALPHA
annotate("<li type=\"a\">")
annotate("<li type=\"a\">")
when ListBase::LABELED
annotate("<dt>") +
convert_flow(am.flow(fragment.param)) +
convert_flow(am.flow(fragment.param)) +
annotate("</dt>") +
annotate("<dd>")
when ListBase::NOTE
annotate("<tr>") +
annotate("<td valign=\"top\">") +
convert_flow(am.flow(fragment.param)) +
convert_flow(am.flow(fragment.param)) +
annotate("</td>") +
annotate("<td>")
else
@ -273,7 +269,8 @@ module SM
def list_end_for(fragment_type)
case fragment_type
when ListBase::BULLET, ListBase::NUMBER, ListBase::UPPERALPHA, ListBase::LOWERALPHA
when ListBase::BULLET, ListBase::NUMBER, ListBase::UPPERALPHA,
ListBase::LOWERALPHA
"</li>"
when ListBase::LABELED
"</dd>"
@ -287,3 +284,4 @@ module SM
end
end

View File

@ -50,7 +50,7 @@ module SM
##
# Set up the standard mapping of attributes to LaTeX
#
def init_tags
@attr_tags = [
InlineTag.new(SM::Attribute.bitmap_for(:BOLD), l("\\textbf{"), l("}")),
@ -61,6 +61,7 @@ module SM
##
# Escape a LaTeX string
def escape(str)
# $stderr.print "FE: ", str
s = str.
@ -80,13 +81,12 @@ module SM
##
# Add a new set of LaTeX tags for an attribute. We allow
# separate start and end tags for flexibility
#
def add_tag(name, start, stop)
@attr_tags << InlineTag.new(SM::Attribute.bitmap_for(name), start, stop)
end
##
##
# Here's the client side of the visitor pattern
def start_accepting
@ -116,7 +116,7 @@ module SM
end
def accept_list_start(am, fragment)
@res << list_name(fragment.type, true) <<"\n"
@res << list_name(fragment.type, true) << "\n"
@in_list_entry.push false
end
@ -124,7 +124,7 @@ module SM
if tag = @in_list_entry.pop
@res << tag << "\n"
end
@res << list_name(fragment.type, false) <<"\n"
@res << list_name(fragment.type, false) << "\n"
end
def accept_list_item(am, fragment)
@ -144,6 +144,7 @@ module SM
@res << convert_heading(fragment.head_level, am.flow(fragment.txt))
end
##
# This is a higher speed (if messier) version of wrap
def wrap(txt, line_len = 76)
@ -173,12 +174,8 @@ module SM
res
end
#######################################################################
private
#######################################################################
def on_tags(res, item)
attr_mask = item.turn_on
return if attr_mask.zero?
@ -220,13 +217,12 @@ module SM
res
end
##
# some of these patterns are taken from SmartyPants...
def convert_string(item)
escape(item).
# convert ... to elipsis (and make sure .... becomes .<elipsis>)
gsub(/\.\.\.\./, '.\ldots{}').gsub(/\.\.\./, '\ldots{}').
@ -270,7 +266,7 @@ module SM
when 4 then "\\subsubsection{"
else "\\paragraph{"
end +
convert_flow(flow) +
convert_flow(flow) +
"}\n"
end
@ -304,7 +300,8 @@ module SM
def list_item_start(am, fragment)
case fragment.type
when ListBase::BULLET, ListBase::NUMBER, ListBase::UPPERALPHA, ListBase::LOWERALPHA
when ListBase::BULLET, ListBase::NUMBER, ListBase::UPPERALPHA,
ListBase::LOWERALPHA
"\\item "
when ListBase::LABELED
@ -319,7 +316,8 @@ module SM
def list_end_for(fragment_type)
case fragment_type
when ListBase::BULLET, ListBase::NUMBER, ListBase::UPPERALPHA, ListBase::LOWERALPHA, ListBase::LABELED
when ListBase::BULLET, ListBase::NUMBER, ListBase::UPPERALPHA,
ListBase::LOWERALPHA, ListBase::LABELED
""
when ListBase::NOTE
"\\\\\n"
@ -331,3 +329,4 @@ module SM
end
end