# -*- tab-width: 4 -*- # Copyright (c) 2009 Tim Freeman # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # # (This is the standard MIT License, copied from # http://www.opensource.org/licenses/mit-license.php on 24 Apr 2007.) #desc Shared code between the various HTML files. import time, license_text, sets import os.path email = "tim@fungible.com" email_url = "mailto:" + email me = "Tim Freeman" top_home_url = "http://fungible.com/respect" paper_url = top_home_url + "/paper.html" paper_title = "Using Compassion and Respect to " \ "Motivate an Artificial Intelligence" code_url = top_home_url + "/code" epsilon = "ε" doctype = """""" css = """ """ validator_text = """

Valid HTML 4.01 Strict

""" class BaseDocument(object): def __init__ (self, sourceDirectory=None, sourceURL=None): """sourceDirectory is where we should look for source code files referenced with sourceFileRef. sourceURL is the prefix we should put on the filename to make it into a URL. sourceURL should have a trailing slash if it is nonempty.""" self.sourceDirectory = sourceDirectory self.sourceURL = sourceURL self.definedNames = sets.Set() self.referencedNames = sets.Set() self.parentHeaders = [] # Return a string with the beginning of an HTML file with the given title. # This includes a " result += ""+title+""+css+"\n" result += "" result += self.center(1, title, name=topname) result += self.center(2, self.urlref(email_url, me)) result += self.center(3, "Last modified " + time.ctime()) result += self.center(3, "Canonical URL: " + self.urlref(url)) result += self.center(3, "Copyright (c) %d %s " % ( + license_text.copyright_year, me) \ + self.nameref("mit-license", "MIT License")) return result def coderef(self, sourceFileName, text = None): if text is None: text = sourceFileName assert self.sourceDirectory is not None path = self.sourceDirectory+"/"+sourceFileName assert os.path.exists(path), "No file named " + path return self.urlref(self.sourceURL + sourceFileName + ".txt", text) def imageref(self, imageFileName): assert self.sourceDirectory is not None imageDirectory = self.sourceDirectory + "/images" path = imageDirectory + "/" + imageFileName assert os.path.exists(path), "No file named " + path return "\""" def my_email(self): return self.urlref(email_url, email) def nameref(self, name, text): self.referencedNames.add(name) return self.__urlref("#" + name, text) def urlref(self, url, text=None): if url.startswith("#"): raise Exception("use nameref instead of urlref to reference " + \ url) return self.__urlref(url, text) def __urlref(self, url, text): if text is None: text = url return "" + text + "" def namedef(self, name): if name in self.definedNames: raise Exception("Multiple definition of " + name) self.definedNames.add(name) return "" def __checkNames(self): for name in self.referencedNames: if name not in self.definedNames: raise Exception("The name " + name + \ " was referenced but not defined.") def end(self): html_license = license_text.license(self.urlref) html_license = html_license.replace("\n\n", "\n

\n") result = self.h2("mit-license", "License") \ + html_license + validator_text \ + """" self.__checkNames() return result def center(self, size, text, name=None): return self.h(size=size, name=name, text=text, cssclass="center") def h1(self, name, text): return self.h(1, name, text) def h2(self, name, text): return self.h(2, name, text) def h3(self, name, text): return self.h(3, name, text) def h4(self, name, text): return self.h(4, name, text) # "class" is a reserved word, so I have to call it "cssclass". def h(self, size, name, text, cssclass = None): assert size > 0 and size <= 4 headerIndex = size - 1 self.parentHeaders[headerIndex:] = [] # parentName will be the name of the parent section, if it had one. parentName = None if name is None: nametext = "" else: if len(self.parentHeaders) < headerIndex: raise Exception ("No parent header name for " + name) assert len(self.parentHeaders) == headerIndex self.parentHeaders.append(name) if headerIndex > 0: parentName = self.parentHeaders[headerIndex - 1] nametext = self.namedef(name) if cssclass is None: classtext = "" else: classtext = " class=\"" + cssclass + "\"" hsize = "h" + str(size) assert text is not None if parentName is not None: text = self.nameref(parentName, text) return "<" + hsize + classtext + ">" + nametext + text \ + "

\n" class IndexDocument(BaseDocument): def __init__(self, **kwargs): BaseDocument.__init__(self, **kwargs) self.__startLevel = 1 self.__indentLevel = 1 self.__contents = "" def __add(self, text): self.__contents += text def __indentTo(self, level): if self.__indentLevel == 1: self.__contents = self.__contentsHeader() while self.__indentLevel < level: self.__add("

") self.__indentLevel -= 1 def formatContents(self): self.__indentTo(1) return self.__contents def __contentsHeader(self): return BaseDocument.h(self, 2, name=None, text="Contents") def contents(self, documentGenerator): # We get here when documentGenerator is generating the table # of contents during the pass when we're collecting data for # the table of contents. Just put the header there. return self.__contentsHeader() def h(self, size, name, text, cssclass=None): result = BaseDocument.h(self, size, name, text, cssclass) if name is not None: self.__indentTo(size) self.__add("
  • " + self.nameref(name, text) + "\n") return result class RealDocument(BaseDocument): def __init__(self, **kwargs): self.__kwargs = kwargs BaseDocument.__init__(self, **kwargs) def contents(self, documentGenerator): """Generate a table of contents. contentsName is the name to use for the contents section. documentGenerator is a callable that takes an instance of BaseDocument and calls all the methods to generate the entire document on it. """ indexDocument = IndexDocument(**self.__kwargs) documentGenerator(indexDocument) return indexDocument.formatContents() # A typical document looks like: # def documentGenerator(documentFormatter): # d = documentFormatter # return d.start("My document", "http://url", "top") \ # + d.contents(documentGenerator) \ # + d.h2("body", "The body of my document") \ # + "The body of my document" # + d.end() # print documentGenerator(RealDocument())