Skip to content

Commit

Permalink
Adding docbook support.
Browse files Browse the repository at this point in the history
  • Loading branch information
Russ Olsen committed Jan 13, 2012
1 parent fe3970b commit 8282df9
Show file tree
Hide file tree
Showing 9 changed files with 238 additions and 17 deletions.
2 changes: 1 addition & 1 deletion Rakefile
Expand Up @@ -11,7 +11,7 @@ end

desc "Run notroff"
task :run do |t|
sh "ruby -Ilib -rnotroff bin/notroff test.nr out.html"
sh "ruby -Ilib -rnotroff bin/notroff -d test.nr test.xml"
end


Expand Down
9 changes: 3 additions & 6 deletions bin/notroff
Expand Up @@ -7,19 +7,16 @@ options={}
formatter_class = HtmlFormatter

while true
if ARGV.first == '-fn'
options[:fn] = true
ARGV.shift
elsif ARGV.first == '-html'
formatter_class = HtmlFormatter
if ARGV.first == '-d'
formatter_class = DocbookFormatter
ARGV.shift
else
break
end
end

unless ARGV.size == 2
raise "Usage: notroff <nr file> <output file>"
raise "Usage: notroff [-d] <nr file> <output file>"
end


Expand Down
5 changes: 1 addition & 4 deletions lib/notroff.rb
Expand Up @@ -11,11 +11,8 @@
require "notroff/processor"
require "notroff/command_processor"
require "notroff/composite_processor"
#require "notroff/processor"
require "notroff/tokenize"
#require "notroff/odt_renderer"
require "notroff/html_renderer"
#require "notroff/odt_replacer"
#require "notroff/template_expander"
require "notroff/docbook_renderer"
require "notroff/formatter"
require "notroff/filter"
15 changes: 12 additions & 3 deletions lib/notroff/composite_processor.rb
Expand Up @@ -16,12 +16,21 @@ def process(paras=[])
puts "Applying processor #{processor.class} to #{paras.size} paragraphs"
paras = processor.process( paras )
puts "After processor #{processor.class}"
puts "Now have #{paras.size} paragraphs" if paras
p paras
puts "========="
dump(paras)
end
paras
end

def dump(array)
if array.nil?
puts "Array: #{array}"
else
puts "======="
puts "Array with #{array.size} items:"
array.each_with_index {|item, i| puts "[#{i}] - #{item}" }
puts "======="
end
end
end


Expand Down
155 changes: 155 additions & 0 deletions lib/notroff/docbook_renderer.rb
@@ -0,0 +1,155 @@
require 'rexml/document'
require 'pp'

class DocbookRenderer < Processor
include Tokenize
include REXML

def process( paragraphs )
@author = 'John Smith'
@title = 'Wealth of Nations'
@chapters = []
@chapter = nil
@section = nil

paragraphs.each do |paragraph|
format( paragraph )
end
@book = Element.new('book')
@book.add_namespace('http://docbook.org/ns/docbook')
@book.add_attribute('version', '5.0')
@book.add_element element_for('title', @title)
@book.add_element element_for('author', @author)
@chapters.each {|ch| @book << ch}
doc = Document.new
decl = XMLDecl.new
decl.version = '1.0'
doc << decl
doc << @book
doc
end

def element_for(type, text)
result = Element.new(type)
result.add_text(text)
result
end

def format( p )
type = p[:type]
text = p.string

return nil if text.empty? and :type != :code

case type
when :title
@title = text
when :author
@author = text
when :chapter
puts "adding chapter #{text}"
@chapter = Element.new('chapter')
@chapters << @chapter
@section = nil
title_element = Element.new('title')
add_body_text(title_element, text)
@chapter.add_element(title_element)
when :section
puts "adding section #{text}"
@section = Element.new('section')
@chapter.add(@section)
title_element = Element.new('title')
add_body_text(title_element, text)
@section.add_element(title_element)
when :body
puts "adding body #{text[0..5]}"
paragraph = Element.new('para')
add_body_text(paragraph, text)
add_content_element(paragraph)
when :code
add_content_element(code_element(type, text))
else
raise "#{type}???"
end
end

def add_content_element(el)
if @section
@section.add_element(el)
elsif @chapter
@chapter.add_element(el)
else
raise "No chapter to add #{el} to"
end
end

def text_element(type, text)
element = [ tag_for(type) ]
add_body_text(element, text)
element
end

def tag_for(type)
case type
when :body
'para'
when :text
'p'
when :author
'h3'
when :section
'h3'
when :chapter
'chapter'
when :sec
'h3'
when :title
'h2'
else
raise "Dont know what to do with #{type}"
end
end

def add_body_text( element, text )
tokens = tokenize_body_text( text )
tokens.each {|token| add_span( token, element ) }
end

def add_span( token, element )
puts "Add span: token: #{token} element: #{element}"
case token[:type]
when :italic
element.add( span_for( token.string, "emphasis" ))
when :code
element.add( span_for( token.string, "code" ))
when :bold
element.add( span_for( token.string, "emphasis" ))
when :normal
element.add_text( token.string )
when :footnote
element.add(footnote_for(token.string))
else
raise "Dont know what to do with #{token}"
end
end

def footnote_for( text )
fn = Element.new('footnote')
fn.add_element(element_for('para', text))
fn
end

def code_element(type, text)
element = Element.new('informalexample')
prog_element = element_for('programlisting', text)
prog_element.add_attribute('xml:space', 'preserve')
element.add_element(prog_element)
element
end

def span_for( text, style )
span = Element.new(style)
span.text = remove_escapes(text)
span
end
end
16 changes: 14 additions & 2 deletions lib/notroff/embedded.rb
@@ -1,5 +1,5 @@
class BetweenFilter
def initialize(re1, re2)
def initialize(re1, re2=re1)
@re1 = re1
@re2 = re2
end
Expand All @@ -10,6 +10,7 @@ def process(paras)
if state == :before_first and @re1 =~ para
para[:included] = true
state = :after_first
break if para =~ @re2
elsif state == :after_first
para[:included] = true
break if para =~ @re2
Expand Down Expand Up @@ -57,6 +58,12 @@ def initialize(class_name, include_body)
end
end

class ModuleFilter < DefinitionFilter
def initialize(module_name, include_body)
super /^ *module +#{module_name}(\(|$| )/, include_body
end
end

class EmbeddedRubyProcessor
def process(paragraphs)
new_paragraphs = []
Expand All @@ -80,6 +87,7 @@ def process_command(ruby_expression)
def embed(*filters, &block)
paras = block.call.map {|line| line.rstrip}
paras.map! {|p| Text.new(p, :type => :code)}
puts "EMBED: #{paras}"
unless filters.empty?
filters.each {|f| paras = f.process(paras)}
paras = paras.find_all {|p| p[:included]}
Expand All @@ -95,7 +103,7 @@ def run(command, *filters)
embed(*filters) {File.popen(command).readlines}
end

def between(re1, re2)
def matches(re1, re2=re1)
BetweenFilter.new(re1, re2)
end

Expand All @@ -107,6 +115,10 @@ def clazz(name, include_body=true)
ClassFilter.new(name, include_body)
end

def mod(name, include_body=true)
ModuleFilter.new(name, include_body)
end

def indent(delta_indent, paragraphs)
paragraphs.map do |p|
if delta_indent > 0
Expand Down
10 changes: 10 additions & 0 deletions lib/notroff/formatter.rb
Expand Up @@ -19,6 +19,16 @@ def initialize(input, output)
end
end

class DocbookFormatter < Formatter
def initialize(input, output)
super()
prepend_processor FileReader.new(input)
add_processor CodeParagraphJoiner.new
add_processor DocbookRenderer.new
add_processor FileWriter.new(output)
end
end




Expand Down
2 changes: 1 addition & 1 deletion lib/notroff/paragraph_joiner.rb
Expand Up @@ -42,7 +42,7 @@ def join?(paragraph)
end

def skip?(paragraph)
paragraph.empty?
paragraph[:type] == :body && paragraph.empty?
end
end

Expand Down
41 changes: 41 additions & 0 deletions test.nr
@@ -0,0 +1,41 @@
.title The Roots of Ruby
.author Fogus and Russ
.chapter The Way of the World
AAAAA In more

this is ~~italics~~ and

this is a footnote {{foot notes}} and

this is @@code@@ and

this is !!bold!! is book.
All DocBook elements are in an XML Namespace, so the root element has an xmlns attribute to set the current namespace. Also, the root element of a DocBook document must have a version that specifies the version of the format that the document is built on.

.section A section
In more detail, the root element of the document is book. All DocBook elements are in an XML Namespace, so the root element has an xmlns attribute to set the current namespace. Also, the root element of a DocBook document must have a version that specifies the version of the format that the document is built on.
Some code
.code

# A comment surrouded by white space


# Another comment



.body
body line
.chapter A second chapter
More intro text
.section Section 1
section 1 text
more body
text
.code
foo = bar
bar = foo
.body
still more body text
.section Two
section 2 text

0 comments on commit 8282df9

Please sign in to comment.