]> Shamusworld >> Repos - ardour-manual-diverged/blobdiff - build.rb
Merge branch 'master' of http://shamusworld.gotdns.org/git/ardour-manual
[ardour-manual-diverged] / build.rb
old mode 100644 (file)
new mode 100755 (executable)
index 8246d8e..82693f1
--- a/build.rb
+++ b/build.rb
@@ -1,34 +1,46 @@
+#!/usr/bin/env ruby
+
 require 'pathname'
-require 'fileutils'
 require 'yaml'
-require 'liquid'
+require 'optparse'
 
-def split_frontmatter(txt)
-    re = /\A---[ \t\r]*\n(?<frontmatter>.*?)^---[ \t\r]*\n(?<content>.*)\z/m
-    match = re.match txt 
-    match ? [match['frontmatter'], match['content']] : nil
+begin require 'liquid'
+rescue LoadError
+    puts "Please install the 'liquid' Ruby gem (available in Debian/Ubuntu as 'ruby-liquid')"
+    exit 1
 end
 
+CONFIG = {
+    pages_dir: '_manual',
+    layouts_dir: '_layouts',
+    static_dir: 'source',
+    output_dir: '_site'
+}
+
 def child_url?(a, b)
     a.start_with?(b) && b.count('/') + 1 == a.count('/')
 end
 
 class Site
-    attr_reader :pages
+    attr_reader :pages, :layouts
 
     def initialize()
         @pages = []
-        @config = {
-            'pages_dir' => '_manual',
-            'layouts_dir' => '_layouts',
-            'static_dir' => 'source',
-            'output_dir' => '_site'
-        }
         @layouts = {}
     end
     
+    def build()
+        print "Building... "
+
+        read_layouts()
+        read_pages()
+        copy_static()
+        process_pages()
+
+        puts "done."
+    end
+
     def read_layouts()
-        layouts_dir = Pathname(@config['layouts_dir'])
         Pathname.glob(layouts_dir + Pathname('*.html')) do |path|
             next if !path.file?
             layout = Layout.new(self, path)
@@ -37,12 +49,7 @@ class Site
         end
     end
     
-    def find_layout(name)
-        @layouts[name]
-    end
-    
     def read_pages()
-        pages_dir = Pathname.new(@config['pages_dir'])
         pages_dir.find do |path|
             if path.file? && path.extname == '.html'
                 page = Page.new(self, path)
@@ -52,33 +59,27 @@ class Site
         end
     end
 
-    def find_children(url)
-        @pages.select{ |p| child_url?(p.url, url) }.sort_by{ |p| p.path.basename }
-    end
-    
     def process_pages()
         @pages.each {|page| page.process}
     end
     
     def copy_static()
-        # http://ruby-doc.org/stdlib-2.2.1/libdoc/fileutils/rdoc/index.html
+        unless system("rsync -a --delete --exclude='*~' #{static_dir}/. #{output_dir}")
+            puts "Couldn't copy static files, is rsync installed?"
+        end
     end
     
-    def pages_dir()
-        Pathname(@config['pages_dir'])
+    def find_children(url)
+        sorted_pages.select { |p| child_url?(p.url, url) }
     end
     
-    def output_dir()
-        Pathname(@config['output_dir'])
-    end
+    def toplevel() @toplevel_memo ||= find_children('/') end
+    def sorted_pages() @sorted_pages_memo ||= @pages.sort_by{ |p| p.sort_url } end
 
-    def run()
-        #read_config()
-        read_layouts()
-        read_pages()
-        copy_static()
-        process_pages()
-    end
+    def pages_dir() @pages_dir_memo ||= Pathname(CONFIG[:pages_dir]) end
+    def layouts_dir() @layouts_dir_memo ||= Pathname(CONFIG[:layouts_dir]) end
+    def static_dir() @static_dir_memo ||= Pathname(CONFIG[:static_dir]) end
+    def output_dir() @output_dir_memo ||= Pathname(CONFIG[:output_dir]) end
 end
 
 class Page
@@ -88,18 +89,16 @@ class Page
         @site = site
         @path = path
 
-        canon = canonical
-        @out_path = @site.output_dir + canon + Pathname("index.html")
-        @url = '/' + canon + '/'
-        @sort_url = @path.to_s.sub(/\.html$/, '')
-    end
+       relative_path = @path.relative_path_from(@site.pages_dir);
+       a = relative_path.each_filename.map do |x|
+            x.sub(/^[0-9]*[-_]/, '')
+        end
+       a[-1].sub!(/\.html$/, '')
+        s = a.join('/')
 
-    def canonical()
-        remove_numbers = lambda {|x| x.sub(/^[0-9]*[-_]/, '') }
-        path = @path.relative_path_from(@site.pages_dir)
-        a = path.each_filename.map(&remove_numbers)
-        a[-1] = a[-1].sub(/\.html$/, '')
-        a.join('/')
+        @out_path = @site.output_dir + Pathname(s) + Pathname("index.html")
+        @url = "/#{s}/"
+        @sort_url = @path.to_s.sub(/\.html$/, '')
     end
 
     def related_to?(p)
@@ -108,27 +107,32 @@ class Page
     end
 
     def title()
-        if !@page_context
-            puts 'nil page context: ' + @path.to_s
-        end
         @page_context['title'] || ""
     end
 
+    def menu_title()
+        @page_context['menu_title'] || title
+    end
+
     def read()
         content = @path.read
-        split = split_frontmatter content
-        split || abort("Not a Jekyll-formatted file: #{@path}") 
-        frontmatter, @content = split
+        frontmatter, @content = split_frontmatter(content) || abort("File not well-formatted: #{@path}") 
         @page_context = YAML.load(frontmatter)
         @template = Liquid::Template.parse(@content)
     end        
+
+    def split_frontmatter(txt)
+        @split_regex ||= /\A---[ \t\r]*\n(?<frontmatter>.*?)^---[ \t\r]*\n(?<content>.*)\z/m
+        match = @split_regex.match txt 
+        match ? [match['frontmatter'], match['content']] : nil
+    end
     
     def find_layout()
-        @site.find_layout(@page_context['layout'] || 'default')
+        @site.layouts[@page_context['layout'] || 'default']
     end
 
     def children()
-        @site.find_children(@url)
+        @children ||= @site.find_children(@url)
     end
     
     def render()
@@ -175,7 +179,7 @@ class Tag_tree < Liquid::Tag
             
             %{
           <dt#{css}>
-            <a href='#{page.url}'>#{page.title}</a>
+            <a href='#{page.url}'>#{page.menu_title}</a>
           </dt>
           <dd#{css}>
             #{children_html}
@@ -183,7 +187,7 @@ class Tag_tree < Liquid::Tag
         }
         end
 
-        join(site.find_children('/').map(&format_entry))
+        join(site.toplevel.map(&format_entry))
     end
 end
 
@@ -204,30 +208,78 @@ end
 
 class Tag_prevnext < Liquid::Tag
     def render(context)
-        site = context.registers[:site]
         current = context.registers[:page]
+        pages = context.registers[:site].sorted_pages
         
-        pages = site.pages.sort_by{ |p| p.sort_url }
+        index = pages.index { |page| page == current }
+        return '' if !index
         
-        ind = pages.index { |page| page == current }
-        return '' if !ind
-        
-        lnk = lambda do |p, cls, txt| 
+        link = lambda do |p, cls, txt| 
             "<li><a title='#{p.title}' href='#{p.url}' class='#{cls}'>#{txt}</a></li>"
         end
-        prev_link = ind > 0 ? lnk.call(pages[ind-1], "previous", " &lt; Previous ") : ""
-        next_link = ind < pages.length-1 ? lnk.call(pages[ind+1], "next", " Next &gt; ") : ""
+        prev_link = index > 0 ? link.call(pages[index-1], "previous", " &lt; Previous ") : ""
+        next_link = index < pages.length-1 ? link.call(pages[index+1], "next", " Next &gt; ") : ""
         
         "<ul class='pager'>#{prev_link}#{next_link}</ul>"
     end
 end
 
-Liquid::Template.register_tag('tree', Tag_tree)
-Liquid::Template.register_tag('children', Tag_children)
-Liquid::Template.register_tag('prevnext', Tag_prevnext)
+class Server
+    def start_watcher()
+        begin require 'listen'
+        rescue LoadError
+            puts "To use the --watch function, please install the 'listen' Ruby gem"
+            puts "(available in Debian/Ubuntu as 'ruby-listen')"
+            return nil
+        end
+
+        listener = Listen.to(CONFIG[:pages_dir], wait_for_delay: 1.0, only: /.html$/) do |modified, added, removed|
+            Site.new.build
+        end
+        listener.start
+        listener
+    end
+
+    def run(options)
+        require 'webrick'
+       listener = options[:watch] && start_watcher
+        port = options[:port] || 8000
+           
+        puts "Serving at http://localhost:#{port}/ ..."
+        server = WEBrick::HTTPServer.new :Port => port, :DocumentRoot => CONFIG[:output_dir]
+       trap 'INT' do 
+            server.shutdown 
+        end
+       server.start
+        listener.stop if listener
+    end  
+end
+
+def main
+    Liquid::Template.register_tag('tree', Tag_tree)
+    Liquid::Template.register_tag('children', Tag_children)
+    Liquid::Template.register_tag('prevnext', Tag_prevnext)
 
-if defined? Liquid::Template.error_mode
-    Liquid::Template.error_mode = :strict
+    if defined? Liquid::Template.error_mode
+        Liquid::Template.error_mode = :strict
+    end
+
+    options = {}
+    OptionParser.new do |opts| 
+       opts.banner = %{Usage: build.rb <command> [options]
+
+Use 'build.rb' to build the manual.  Use 'build.rb serve' to also
+start a web server; setting any web server options implies "serve".
+}
+        opts.on("-w", "--watch", "Watch for changes") { options[:watch] = true }
+        opts.on("-p", "--port N", Integer, "Specify port for web server") { |p| options[:port] = p }
+    end.parse!
+
+    Site.new.build
+
+    if options[:watch] || options[:port] || (ARGV.length > 0 && "serve".start_with?(ARGV[0]))
+        Server.new.run(options)
+    end
 end
 
-Site.new.run
+main