Skip to content

Instantly share code, notes, and snippets.

@phyrog
Last active February 10, 2016 16:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save phyrog/3dbbb64425d9d5f7ffe2 to your computer and use it in GitHub Desktop.
Save phyrog/3dbbb64425d9d5f7ffe2 to your computer and use it in GitHub Desktop.
Generator for chicken scheme documentation
require "rake"
require "tmpdir"
require "fileutils"
require "nokogiri"
require "pathname"
require "base64"
tmpdir = Dir.mktmpdir
setdir = "#{tmpdir}/chicken.docset"
condir = "#{setdir}/Contents"
dbdir = "#{condir}/Resources"
docdir = "#{dbdir}/Documents"
mandir = "#{docdir}/manual"
eggdir = "#{docdir}/eggs"
icon = <<-IMG
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gwTFjEzApp76QAAAkRJREFUOMuNkkFIFFEYx38zzqASppBIhzEyZAgmsoMRHYYKa2ybSw50CIqIDgOph5hYjE5hEA1NGBSxyCZ5LUaotomFDjUZdTE6rODaqaYyJSoioyadLrvbulj0Lu993/v//+993/cXYl9HtkJiX98LHASGgQ+yFfI/SyyRTwL3gDdA8W/gwFT3BaZ6KzDVzopA7OutwAjQIVvhRWAaSNWS76fU3cBtIAs8qQgAO4ErshW+L+Vc4EQ1eWpwa8f6zoZzXT3N21K54gOgMTBVCUD46estsvRLG3nXPjnQVtZgHtCABalPRRCyAMS+flW2woHAVONUrigDSL2zWryUCN2Ph65PniqxY18/BMwC3YKQfRX7egswClzwjc4toiBM/mmikMgN4vKw4dqt5aRshY+AXcBo7OszgA+cla1wqqm+rq8YLW4qYyXgK9AIdAEPq0p/KVvhnkpN13YQmKq0lCTO8jITnqYcB8ZEoB74DhytblytD9r6nwNcThJuLHyO+4GLTiFCBNqBJmB8lblXnw8DRwDn/Ou5ReCLpylrxHw6MwMcA85UXvcvEZiqCIiBqW4PTHUCyACbgaQEi4AWESCfzowDc4ZrTxmuPRhbpwHWARuAb0A2lSuuBeZTuYpR251C9BYAw7XLe6/h2jf/VYqnKXiaonmacndVvxuu/cJw7Z6qeMW9pyn7PU2ZLosJNWTy6QyGaw+UxjqWT2eeeppSB2wEhoBnTiHKepqCU4hWCqzyGwX4cSB759OSVNfsFKKPtZjfuy3Givmt3nYAAAAASUVORK5CYII=
IMG
typemappings = {
"syntax" => "builtin",
}
def insert_search_entry(entry, dbdir)
sqlstring = <<-SQLEND
INSERT OR IGNORE INTO searchIndex(name, type, path) VALUES ("#{entry[:name]}", "#{entry[:type]}", "#{entry[:path]}");
SQLEND
puts sqlstring
system("sqlite3", "#{dbdir}/docSet.dsidx", sqlstring)
end
task :default => [:make_tgz] do
puts "Output in: #{tmpdir}"
end
task :clone_repo do
print "Checking out svn repo... "
`svn co --username anonymous --password \"\" http://code.call-cc.org/svn/chicken-eggs/wiki #{tmpdir}/svn`
puts "Done."
end
task :build_manual => [:clone_repo] do
FileUtils.mkdir_p mandir
print "Creating HTML output for manual... "
`manual-labor #{tmpdir}/svn/manual #{mandir}`
puts "Done."
end
task :build_eggs => [:clone_repo] do
FileUtils.mkdir_p eggdir
print "Creating HTML output for eggs... "
`manual-labor #{tmpdir}/svn/egg #{eggdir}`
puts "Done."
end
task :create_plist => [:build_manual, :build_eggs] do
plist = <<-PLISTEND
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>chicken</string>
<key>CFBundleName</key>
<string>Chicken</string>
<key>DocSetPlatformFamily</key>
<string>chicken</string>
<key>isDashDocset</key>
<true/>
</dict>
</plist>
PLISTEND
print "Creating Info.plist... "
File.open("#{condir}/Info.plist", 'w') do |file|
file.write(plist)
end
puts "Done."
end
task :create_icon => [:build_manual, :build_eggs] do
print "Creating icon.png... "
File.open("#{setdir}/icon.png", 'w') { |f| f.write(Base64.decode64(icon)) }
puts "Done."
end
task :create_db do
sqlstring = <<-SQLEND
CREATE TABLE searchIndex(id INTEGER PRIMARY KEY, name TEXT, type TEXT, path TEXT);
CREATE UNIQUE INDEX anchor ON searchIndex (name, type, path);
SQLEND
print "Creating database... "
`sqlite3 #{dbdir}/docSet.dsidx '#{sqlstring}'`
puts "Done."
end
def rel_path(from, to)
Pathname.new(to).relative_path_from(Pathname.new(from))
end
def escape_name(name)
name.gsub(/.*»\s*(.+)/, '\1').gsub("\"", %q("")).gsub(/\(+(\S+).*\).*/, '\1').strip
end
task :insert_manual => [:build_manual, :create_db] do
print "Populating manual search index... "
Dir.foreach(mandir) do |item|
unless item == '.' or item == '..'
page = Nokogiri::HTML(open("#{mandir}/#{item}"))
entry = {
name: escape_name(page.css('title').inner_text),
path: "#{rel_path(docdir, mandir)}/#{item}",
type: "manual"
}
insert_search_entry(entry, dbdir) if (not entry[:name].strip.empty?) && (not entry[:path].strip.empty?) && (not entry[:type].strip.empty?)
page.css('dt.defsig').each do |defsig|
entry = {
name: escape_name(defsig.css('tt').inner_text),
path: "#{rel_path(docdir, mandir)}/#{item}##{defsig["id"]}",
type: typemappings[defsig.css('.type').inner_text.strip.gsub(/\s+/, ' ')] ||
defsig.css('.type').inner_text.strip.gsub(/\s+/, ' ')
}
insert_search_entry(entry, dbdir)
end
end
end
puts "Done."
end
task :insert_eggs => [:build_eggs, :create_db] do
print "Populating egg search index... "
Dir.foreach(eggdir) do |item|
unless item == '.' or item == '..'
page = Nokogiri::HTML(open("#{eggdir}/#{item}"))
entry = {
name: escape_name(page.css('head title').inner_text),
path: "#{rel_path(docdir, eggdir)}/#{item}",
type: "library"
}
insert_search_entry(entry, dbdir) if (not entry[:name].strip.empty?) && (not entry[:path].strip.empty?) && (not entry[:type].strip.empty?)
page.css('dt.defsig').each do |defsig|
entry = {
name: "#{escape_name(defsig.css('tt').inner_text)} [#{File.basename(item, '.*')}]",
path: "#{rel_path(docdir, eggdir)}/#{item}##{defsig["id"]}",
type: typemappings[defsig.css('.type').inner_text.strip.gsub(/\s+/, ' ')] ||
defsig.css('.type').inner_text.strip.gsub(/\s+/, ' ')
}
insert_search_entry(entry, dbdir)
end
end
end
puts "Done."
end
task :make_tgz => [:insert_manual, :insert_eggs, :create_plist, :create_icon] do
print "Creating chicken.tgz... "
`tar -cvzf #{tmpdir}/chicken.tgz -C #{tmpdir} chicken.docset`
puts "Done."
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment