# HG changeset patch
# User John H. Palmieri <palmieri@math.washington.edu>
# Date 1240338630 25200
# Node ID 3d7fce9264e936d6978bc1bc3f199b55fea431cd
# Parent  7f9164053b2a6e9302193d8a3c710b826c6041cf
pretty docstrings in notebook

diff --git a/doc/introspect/__init__.py b/doc/introspect/__init__.py
new file mode 100644
--- /dev/null
+++ b/doc/introspect/__init__.py
@@ -0,0 +1,1 @@
+ 
diff --git a/doc/introspect/builder.py b/doc/introspect/builder.py
new file mode 100644
--- /dev/null
+++ b/doc/introspect/builder.py
@@ -0,0 +1,668 @@
+#!/usr/bin/env python
+import os, sys, subprocess, shutil, glob, optparse
+
+#We remove the current directory from sys.path right away
+#so that we import sage from the proper spot
+try:
+    sys.path.remove(os.path.realpath(os.getcwd()))
+except:
+    pass
+
+from sage.misc.cachefunc import cached_method
+
+##########################################
+#                Options                 #
+##########################################
+SAGE_DOC = os.environ['SAGE_DOC']
+LANGUAGES = ['en', 'fr']
+SPHINXOPTS  = ""
+PAPER       = ""
+
+if PAPER == "a4":
+    PAPEROPTS = "-D latex_paper_size=a4"
+elif PAPER == "letter":
+    PAPEROPTS = "-D latex_paper_size=letter"
+else:
+    PAPEROPTS = ""
+
+#Note that this needs to have the doctrees dir    
+ALLSPHINXOPTS   = SPHINXOPTS + " " + PAPEROPTS + " . "
+
+
+##########################################
+#          Utility Functions             #
+##########################################
+def mkdir(path):
+    """
+    Makes the directory at path if it doesn't exist and returns the
+    string path.
+
+    EXAMPLES::
+
+        sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
+        sage: d = tmp_filename(); d
+        '/.../tmp_...'
+        sage: os.path.exists(d)
+        False
+        sage: dd = builder.mkdir(d)
+        sage: d == dd
+        True
+        sage: os.path.exists(d)
+        True
+    """
+    if not os.path.exists(path):
+        os.makedirs(path)
+    return path
+
+def copytree(src, dst, symlinks=False, ignore_errors=False):
+    """
+    Recursively copy a directory tree using copy2().
+
+    The destination directory must not already exist.
+    If exception(s) occur, an Error is raised with a list of reasons.
+
+    If the optional symlinks flag is true, symbolic links in the
+    source tree result in symbolic links in the destination tree; if
+    it is false, the contents of the files pointed to by symbolic
+    links are copied.
+
+    XXX Consider this example code rather than the ultimate tool.
+
+    """
+    names = os.listdir(src)
+    mkdir(dst)
+    errors = []
+    for name in names:
+        srcname = os.path.join(src, name)
+        dstname = os.path.join(dst, name)
+        try:
+            if symlinks and os.path.islink(srcname):
+                linkto = os.readlink(srcname)
+                os.symlink(linkto, dstname)
+            elif os.path.isdir(srcname):
+                copytree(srcname, dstname, symlinks)
+            else:
+                shutil.copy2(srcname, dstname)
+            # XXX What about devices, sockets etc.?
+        except (IOError, os.error), why:
+            errors.append((srcname, dstname, str(why)))
+        # catch the Error from the recursive copytree so that we can
+        # continue with other files
+        except shutil.Error, err:
+            errors.extend(err.args[0])
+    try:
+        shutil.copystat(src, dst)
+    except OSError, why:
+        errors.extend((src, dst, str(why)))
+    if errors and not ignore_errors:
+        raise shutil.Error, errors
+
+
+
+##########################################
+#             Builders                   #
+##########################################
+def builder_helper(type):
+    """
+    Returns a function which builds the documentation for
+    output type type.
+    """
+    def f(self):
+        output_dir = self._output_dir(type)
+        os.chdir(self.dir)
+
+        build_command = 'sphinx-build'
+        build_command += ' -b %s -d %s %s %s'%(type, self._doctrees_dir(),
+                                               ALLSPHINXOPTS, output_dir)
+        print build_command
+        subprocess.call(build_command, shell=True)
+
+        print "Build finished.  The built documents can be found in %s"%output_dir
+        
+    f.is_output_format = True
+    return f
+        
+
+class DocBuilder(object):
+    def __init__(self, name, lang='en'):
+        """
+        INPUT:
+            
+        - ``name`` - the name of a subdirectory in SAGE_DOC, such as
+          'tutorial' or 'bordeaux_2008'
+
+        - ``lang`` - (default "en") the language of the document.
+        """
+        if '/' in name:
+            lang, name = name.split(os.path.sep)
+        self.name = name
+        self.lang = lang
+        self.dir = os.path.join(SAGE_DOC, lang, name)
+
+        #Make sure the .static and .templates directories are there
+        mkdir(os.path.join(self.dir, "static"))
+        mkdir(os.path.join(self.dir, "templates"))
+
+    def _output_dir(self, type):
+        """
+        Returns the directory where the output of type type is stored.
+        If the directory does not exist, then it will automatically be
+        created.
+
+        EXAMPLES::
+
+            sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
+            sage: b = builder.DocBuilder('tutorial')
+            sage: b._output_dir('html')
+            '.../devel/sage/doc/output/html/en/tutorial'
+        """
+        return mkdir(os.path.join(SAGE_DOC, "output", type, self.lang, self.name))
+
+    def _doctrees_dir(self):
+        """
+        Returns the directory where the doctrees are stored.  If the
+        directory does not exist, then it will automatically be
+        created.
+
+        EXAMPLES::
+
+            sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
+            sage: b = builder.DocBuilder('tutorial')
+            sage: b._doctrees_dir()
+            '.../devel/sage/doc/output/doctrees/en/tutorial'
+        """
+        return mkdir(os.path.join(SAGE_DOC, "output", 'doctrees', self.lang, self.name))
+
+    def _output_formats(self):
+        """
+        Returns a list of the possible output formats.
+
+        EXAMPLES::
+
+            sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
+            sage: b = builder.DocBuilder('tutorial')
+            sage: b._output_formats()
+            ['changes', 'html', 'htmlhelp', 'json', 'latex', 'linkcheck', 'pickle', 'web']
+
+        """
+        #Go through all the attributes of self and check to
+        #see which ones have an 'is_output_format' attribute.  These
+        #are the ones created with builder_helper.
+        output_formats = []
+        for attr in dir(self):
+            if hasattr(getattr(self, attr), 'is_output_format'):
+                output_formats.append(attr)
+        output_formats.sort()
+        return output_formats
+
+    def pdf(self):
+        """
+        Builds the PDF files for this document.  This is done by first
+        (re)-building the LaTeX output, going into that LaTeX
+        directory, and running 'make all-pdf' there.
+
+        EXAMPLES::
+
+            sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
+            sage: b = builder.DocBuilder('tutorial')
+            sage: b.pdf() #not tested
+        """
+        self.latex()
+        os.chdir(self._output_dir('latex'))
+        subprocess.call('make all-pdf', shell=True)
+
+        pdf_dir = self._output_dir('pdf')
+        for pdf_file in glob.glob('*.pdf'):
+            shutil.move(pdf_file, os.path.join(pdf_dir, pdf_file))
+
+        print "Build finished.  The built documents can be found in %s"%pdf_dir              
+
+    def clean(self, *args):
+        """
+        """
+        import shutil
+        shutil.rmtree(self._doctrees_dir())
+        output_formats = list(args) if args else self._output_formats()
+        for format in output_formats:
+            shutil.rmtree(self._output_dir(format), ignore_errors=True)
+        
+    html = builder_helper('html')
+    pickle = builder_helper('pickle')
+    web = pickle
+    json = builder_helper('json')                       
+    htmlhelp = builder_helper('htmlhelp')
+    latex = builder_helper('latex')
+    changes = builder_helper('changes')
+    linkcheck = builder_helper('linkcheck')
+
+class AllBuilder(object):
+    """
+    A class used to build all of the documentation.
+    """
+    def __getattr__(self, attr):
+        """
+        For any attributes not explicitly defined, we just go through
+        all of the documents and call their attr.  For example,
+        'AllBuilder().json()' will go through all of the documents
+        and call the json() method on their builders.
+        """
+        from functools import partial
+        return partial(self._wrapper, attr)
+
+    def _wrapper(self, name, *args, **kwds):
+        """
+        This is the function which goes through all of the documents
+        and does the actual building.
+        """
+        for document in self.get_all_documents():
+            getattr(get_builder(document), name)(*args, **kwds)
+
+    def get_all_documents(self):
+        """
+        Returns a list of all of the documents. A document is a directory within one of 
+        the language subdirectories of SAGE_DOC specified by the global LANGUAGES
+        variable.
+
+        EXAMPLES::
+
+            sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
+            sage: documents = builder.AllBuilder().get_all_documents()
+            sage: 'en/tutorial' in documents
+            True
+        """
+        documents = []
+        for lang in LANGUAGES:
+            for document in os.listdir(os.path.join(SAGE_DOC, lang)):
+                documents.append(os.path.join(lang, document))
+        return documents
+
+class WebsiteBuilder(DocBuilder):
+    def html(self):
+        """
+        After we've finished building the website index page, we copy
+        everything one directory up.
+        """
+        DocBuilder.html(self)
+        html_output_dir = self._output_dir('html')
+        copytree(html_output_dir,
+                 os.path.realpath(os.path.join(html_output_dir, '..')),
+                 ignore_errors=False)
+
+    def clean(self):
+        """
+        When we clean the output for the website index, we need to
+        remove all of the HTML that were placed in the parent
+        directory.
+        """
+        html_output_dir = self._output_dir('html')
+        parent_dir = os.path.realpath(os.path.join(html_output_dir, '..'))
+        for filename in os.listdir(html_output_dir):
+            parent_filename = os.path.join(parent_dir, filename)
+            if not os.path.exists(parent_filename):
+                continue
+            if os.path.isdir(parent_filename):
+                shutil.rmtree(parent_filename, ignore_errors=True)
+            else:
+                os.unlink(parent_filename)
+
+        DocBuilder.clean(self)
+
+class ReferenceBuilder(DocBuilder):
+    """
+    This the class used to build the reference manual.  It is
+    resposible for making sure the auto generated ReST files for the
+    Sage library are up to date.
+
+    When building any output, we must first go through and check
+    to see if we need to update any of the autogenerated ReST
+    files.  There are two cases where this would happen:
+
+    1. A new module gets added to one of the toctrees.
+    
+    2. The actual module gets updated and possibly contains a new
+       title.
+    """
+    def __init__(self, *args, **kwds):
+        DocBuilder.__init__(self, *args, **kwds)
+        self._wrap_builder_helpers()
+
+    def _wrap_builder_helpers(self):
+        from functools import partial, update_wrapper
+        for attr in dir(self):
+            if hasattr(getattr(self, attr), 'is_output_format'):
+                f = partial(self._wrapper, attr)
+                f.is_output_format = True
+                update_wrapper(f, getattr(self, attr))
+                setattr(self, attr, f)
+    
+    def _wrapper(self, build_type, *args, **kwds):
+        """
+        This is the wrapper around the builder_helper methods that
+        goes through and makes sure things are up to date.
+        """
+        #Write the .rst files for newly included modules
+        for module_name in self.get_newly_included_modules(save=True):
+            self.write_auto_rest_file(module_name)
+
+        #Update the .rst files for modified Python modules
+        for module_name in self.get_modified_modules():
+            self.write_auto_rest_file(module_name.replace(os.path.sep, '.'))
+
+        #Copy over the custom .rst files from _sage
+        _sage = os.path.join(self.dir, '_sage')
+        if os.path.exists(_sage):
+            copytree(_sage, os.path.join(self.dir, 'sage'))
+                
+        getattr(DocBuilder, build_type)(self, *args, **kwds)
+    
+    def cache_filename(self):
+        """
+        Returns the filename where the pickle of the dictionary of
+        already generated .rst files is stored.
+        """
+        return os.path.join(self._doctrees_dir(), 'reference.pickle')
+
+    @cached_method
+    def get_cache(self):
+        """
+        Retreive the cache of already generated .rst files.  If it
+        doesn't exist, then we just return an empty dictionary.
+        """
+        filename = self.cache_filename()
+        if not os.path.exists(filename):
+            return {}
+
+        import cPickle
+        file = open(self.cache_filename(), 'rb')
+        cache = cPickle.load(file)
+        file.close()
+        return cache
+        
+
+    def save_cache(self):
+        """
+        Save the cache of already generated .rst files.
+        """
+        import cPickle
+        file = open(self.cache_filename(), 'wb')
+        cPickle.dump(self.get_cache(), file)
+        file.close()
+
+    def get_sphinx_environment(self):
+        """
+        Returns the Sphinx environment for this project.
+        """
+        from sphinx.environment import BuildEnvironment
+        class Foo(object):
+            pass
+        config = Foo()
+        config.values = []
+
+        env_pickle = os.path.join(self._doctrees_dir(), 'environment.pickle')
+        try:
+            return BuildEnvironment.frompickle(config, env_pickle)
+        except IOError:
+            pass
+                                           
+    def get_modified_modules(self):
+        """
+        Returns an iterator for all the modules that have been modified
+        since the docuementation was last built.
+        """
+        env = self.get_sphinx_environment()
+        if env is None:
+            return
+        added, changed, removed = env.get_outdated_files(False)
+        for name in changed:
+            if name.startswith('sage'):
+                yield name
+
+    def print_modified_modules(self):
+        """
+        Prints a list of all the modules that have been modified since
+        the documentation was last built.
+        """
+        for module_name in self.get_modified_modules():
+            print module_name
+
+    def get_all_rst_files(self, exclude_sage=True):
+        """
+        Returns an iterator for all rst files which are not
+        autogenerated.
+        """
+        for directory, subdirs, files in os.walk(self.dir):
+            if exclude_sage and directory.startswith(os.path.join(self.dir, 'sage')):
+                continue
+            for filename in files:
+                if not filename.endswith('.rst'):
+                    continue
+                yield os.path.join(directory, filename)
+
+    def get_all_included_modules(self):
+        """
+        Returns an iterator for all modules which are included in the
+        reference manual.
+        """
+        for filename in self.get_all_rst_files():
+            for module in self.get_modules(filename):
+                yield module
+
+    def get_newly_included_modules(self, save=False):
+        """
+        Returns an iterator for all modules that appear in the
+        toctrees that don't appear in the cache.
+        """
+        cache = self.get_cache()
+        new_modules = []
+        for module in self.get_all_included_modules():
+            if module not in cache:
+                cache[module] = True
+                yield module
+        if save:
+            self.save_cache()
+
+    def print_newly_included_modules(self):
+        """
+        Prints all of the modules that appear in the toctrees that
+        don't appear in the cache.
+        """
+        for module_name in self.get_newly_included_modules():
+            print module_name
+
+    def get_modules(self, filename):
+        """
+        Given a filename for a .rst file, return an iterator for
+        all of the autogenerated rst files that it includes.
+        """
+        #Create the regular expression used to detect an autogenerated file
+        import re
+        auto_re = re.compile('^\s*(..\/)*(sage\/[\w\/]*)\s*$')
+
+        #Read the lines
+        f = open(filename)
+        lines = f.readlines()
+        f.close()
+
+        for line in lines:
+            match = auto_re.match(line)
+            if match:
+                yield match.group(2).replace(os.path.sep, '.')
+                
+    def get_module_docstring_title(self, module_name):
+        """
+        Returns the title of the module from its docstring.
+        """
+        #Try to import the module
+        try:
+            import sage.all
+            __import__(module_name)
+        except ImportError, err:
+            raise
+            print "Warning: could not import %s"%module_name
+            print err
+            return "UNABLE TO IMPORT MODULE"
+        module = sys.modules[module_name]
+
+        #Get the docstring
+        doc = module.__doc__
+        if doc is None:
+            doc = module.doc if hasattr(module, 'doc') else ""
+
+        #Extract the title
+        i = doc.find('\n')
+        if i != -1:
+            return doc[i+1:].lstrip().splitlines()[0]
+        else:
+            return doc
+
+    def write_auto_rest_file(self, module_name):
+        """
+        Writes the autogenerated .rst file for module_name.
+        """
+        if not module_name.startswith('sage'):
+            return
+        filename = self.dir + os.path.sep + module_name.replace('.',os.path.sep) + '.rst'
+        mkdir(os.path.dirname(filename))
+        
+        outfile = open(filename, 'w')
+
+        title = self.get_module_docstring_title(module_name)
+
+        if title == '':
+            print "WARNING: Missing title for", module_name
+            title = "MISSING TITLE"
+
+        outfile.write(title + '\n')
+        outfile.write('='*len(title) + "\n\n")
+        outfile.write('.. This file has been autogenerated.\n\n')
+        automodule = '.. automodule:: %s\n   :members:\n   :undoc-members:\n\n'
+        outfile.write(automodule%module_name)
+
+        outfile.close()
+
+    def clean_auto(self):
+        """
+        Remove the cache file for the autogenerated files as well as
+        the files themselves.
+        """
+        if os.path.exists(self.cache_filename()):
+            os.unlink(self.cache_filename())
+
+        import shutil
+        shutil.rmtree(self.dir + '/sage')
+
+    def get_unincluded_modules(self):
+        """
+        Returns an iterator for all the modules in the Sage library
+        which are not included in the reference manual.
+        """
+        #Make a dictionary of the included modules
+        included_modules = {}
+        for module_name in self.get_all_included_modules():
+            included_modules[module_name] = True
+        
+        base_path = os.path.join(os.environ['SAGE_ROOT'], 'devel', 'sage', 'sage')
+        for directory, subdirs, files in os.walk(base_path):
+            for filename in files:
+                if not (filename.endswith('.py') or
+                        filename.endswith('.pyx')):
+                    continue
+                
+                path = os.path.join(directory, filename)
+
+                #Create the module name
+                module_name = path[len(base_path):].replace(os.path.sep, '.')
+                module_name = 'sage' + module_name
+                module_name = module_name[:-4] if module_name.endswith('pyx') else module_name[:-3]
+
+                #Exclude some ones  -- we don't want init the manual
+                if module_name.endswith('__init__') or module_name.endswith('all'):
+                    continue
+
+                if module_name not in included_modules:
+                    yield module_name
+                
+    def print_unincluded_modules(self):
+        """
+        Prints all of the modules which are not included in the Sage
+        reference manual.
+        """
+        for module_name in self.get_unincluded_modules():
+            print module_name
+
+    def print_included_modules(self):
+        """
+        Prints all of the modules that are included in the Sage reference
+        manual.
+        """
+        for module_name in self.get_all_included_modules():
+            print module_name
+
+        
+
+def get_builder(name):
+    """
+    Returns a either a AllBuilder or DocBuilder object depending
+    on whether ``name`` is 'all' or not.  These are the objects
+    which do all the real work in building the documentation.
+    """
+    if name == 'all':
+        return AllBuilder()
+    elif name.endswith('reference'):
+        return ReferenceBuilder(name)
+    elif name.endswith('website'):
+        return WebsiteBuilder(name)
+    else:
+        return DocBuilder(name)
+	      
+
+def help_message():
+    """
+    Returns the help message. 
+    """
+    all_b = AllBuilder()
+    docs = all_b.get_all_documents()
+    docs = [(d[3:] if d[0:3] == 'en/' else d) for d in docs]
+    tut_b = DocBuilder('en/tutorial')
+    formats = tut_b._output_formats()
+    formats.remove('html')
+    help = "Usage: sage -docbuild {document} {format}\n"
+    help += "Where {document} is one of:\n    "
+    help += "\n    ".join(docs)
+    help += "\nor 'all' for all documents, and {format} is one of:\n    "
+    help += 'html, pdf, ' + ', '.join(formats)
+    help += "\n"
+    help += "When building the reference manual, there are several additional\n"
+    help += "values for {format}:\n"
+    help += "    print_modified_modules: list modules modified since the documentation\n"
+    help += "         was last built\n"
+    help += "    print_newly_included_modules: list modules added to the\n"
+    help += "         documentation since it was last built\n"
+    help += "    print_unincluded_modules: list modules not included in the documentation\n"
+    help += "    print_included_modules: list modules included in the documentation\n"
+    print help
+
+
+parser = optparse.OptionParser(usage="usage: sage -docbuild [options] name type")
+parser.add_option("--jsmath", action="store_true",
+                  help="render math using jsMath")
+parser.print_help = help_message
+
+if __name__ == '__main__':
+    options, args = parser.parse_args()
+
+    if options.jsmath:
+        os.environ['SAGE_DOC_JSMATH'] = "True"
+
+    #Get the name of the document we are trying to build
+    try:
+        name, type = args
+    except ValueError:
+        print "You must specify the document name and the output format"
+        sys.exit(0)
+   
+    #Make sure common/static exists
+    mkdir(os.path.join(SAGE_DOC, 'common', 'static'))
+
+    #Get the builder and build
+    getattr(get_builder(name), type)()
diff --git a/doc/introspect/conf.py b/doc/introspect/conf.py
new file mode 100644
--- /dev/null
+++ b/doc/introspect/conf.py
@@ -0,0 +1,226 @@
+import sys, os
+SAGE_DOC = os.environ['SAGE_ROOT'] + '/devel/sage/doc'
+
+# If your extensions are in another directory, add it here. If the directory
+# is relative to the documentation root, use os.path.abspath to make it
+# absolute, like shown here.
+#sys.path.append(os.path.abspath('.'))
+
+# General configuration
+# ---------------------
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.jsmath']
+
+jsmath_path = '/javascript_local/jsmath/easy/load.js'
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = [SAGE_DOC + '/introspect/templates', 'templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u""
+copyright = u'2008, The Sage Group'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+# from sage.version import version
+# release = version
+
+#version = '3.1.2'
+# The full version, including alpha/beta/rc tags.
+#release = '3.1.2'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+#unused_docs = []
+
+# List of directories, relative to source directory, that shouldn't be searched
+# for source files.
+exclude_trees = ['.build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+default_role = 'math'
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+
+# Options for HTML output
+# -----------------------
+
+# The style sheet to use for HTML and HTML Help pages. A file of that name
+# must exist either in Sphinx' static/ path, or in one of the custom paths
+# given in html_static_path.
+html_style = 'default.css'
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (within the static path) to place at the top of
+# the sidebar.
+#html_logo = 'sagelogo-word.ico'
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+# html_favicon = 'sageicon.png'
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = [SAGE_DOC +'/introspect/static', 'static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+html_use_modindex = False
+
+# If false, no index is generated.
+html_use_index = False
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = True
+
+# If true, the reST sources are included in the HTML build as _sources/<name>.
+html_copy_source = False
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = ''
+
+# Output file base name for HTML help builder.
+#htmlhelp_basename = ''
+
+
+# Options for LaTeX output
+# ------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, document class [howto/manual]).
+#latex_documents = []
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = 'sagelogo-word.png'
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+#latex_preamble = '\usepackage{amsmath}\n\usepackage{amsfonts}\n'
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_use_modindex = True
+
+
+#####################################################
+
+def process_docstring_aliases(app, what, name, obj, options, docstringlines):
+    """
+    Change the docstrings for aliases to point to the original object.
+    """
+    basename = name.rpartition('.')[2]
+    if hasattr(obj, '__name__') and obj.__name__ != basename:
+        docstringlines[:] = ['See :obj:`%s`.' % name]
+
+def process_docstring_cython(app, what, name, obj, options, docstringlines):
+    """
+    Remove Cython's filename and location embedding.
+    """
+    if len(docstringlines) <= 1:
+        return
+
+    first_line = docstringlines[0]
+    if first_line.startswith('File:') and '(starting at' in first_line:
+        #Remove the first two lines
+        docstringlines.pop(0)
+        docstringlines.pop(0)
+
+def process_docstring_module_title(app, what, name, obj, options, docstringlines):
+    """
+    Removes the first line from the beginning of the module's docstring.  This 
+    corresponds to the title of the module's documentation page.
+    """
+    if what != "module":
+        return
+
+    #Remove any additional blank lines at the beginning
+    title_removed = False
+    while len(docstringlines) > 1 and not title_removed:
+        if docstringlines[0].strip() != "":
+            title_removed = True
+        docstringlines.pop(0)
+
+    #Remove any additional blank lines at the beginning
+    while len(docstringlines) > 1:
+        if docstringlines[0].strip() == "":
+            docstringlines.pop(0)
+        else:
+            break
+
+        
+def setup(app):
+    app.connect('autodoc-process-docstring', process_docstring_cython)
+    app.connect('autodoc-process-docstring', process_docstring_module_title)
diff --git a/doc/introspect/static/.empty b/doc/introspect/static/.empty
new file mode 100644
--- /dev/null
+++ b/doc/introspect/static/.empty
@@ -0,0 +1,1 @@
+ 
\ No newline at end of file
diff --git a/doc/introspect/templates/layout.html b/doc/introspect/templates/layout.html
new file mode 100644
--- /dev/null
+++ b/doc/introspect/templates/layout.html
@@ -0,0 +1,3 @@
+<div class="docstring">
+    {% block body %} {% endblock %}
+</div>
diff --git a/sage/misc/sagedoc.py b/sage/misc/sagedoc.py
--- a/sage/misc/sagedoc.py
+++ b/sage/misc/sagedoc.py
@@ -20,29 +20,38 @@
 #*****************************************************************************
 
 import os
-#('\\item', '*'), \
-substitutes = [('\\_','_'),\
-               ('\\item', '* '), \
-               ('\\to', '-->'), \
-               ('<BLANKLINE>',''), \
-               ('\\leq', '<='), \
-               ('\\geq', '>='), \
-               ('\\le', '<='), \
-               ('\\ge', '>='), \
-               ('\\bf', ''),\
-               ('\\sage', 'SAGE'), \
-               ('\\SAGE', 'SAGE'), \
-               ('\\rm', ''), \
-               ('cdots', '...'), \
-               ('\\cdot', ' *'), \
-               ('$',''), ('\\',''), ('backslash','\\'), \
-               ('begin{enumerate}',''), ('end{enumerate}',''), \
-               ('begin{description}',''), ('end{description}',''), \
-               ('begin{itemize}',''), ('end{itemize}',''), \
-               ('begin{verbatim}',''), ('end{verbatim}',''), \
-               ('mapsto', ' |--> '), \
-               ('ldots', '...'), ('note{','NOTE: ')]
-
+# two kinds of substitutions: math, which should only be done on the
+# command line -- in the notebook, these should instead by taken care
+# of by jsMath -- and nonmath, which should be done always.
+math_substitutes = [('\\to', '-->'),
+                    ('\\leq', '<='),
+                    ('\\geq', '>='),
+                    ('\\le', '<='),
+                    ('\\ge', '>='),
+                    ('cdots', '...'),
+                    ('\\cdot', ' *'),
+                    (' \\times', ' x'),
+                    ('\\times', ' x'),
+                    ('backslash','\\'),
+                    ('mapsto', ' |--> '),
+                    ('ldots', '...')]
+nonmath_substitutes = [('\\_','_'),
+                       ('\\item', '* '),
+                       ('<BLANKLINE>',''),
+                       ('\\bf', ''),
+                       ('\\sage', 'SAGE'),
+                       ('\\SAGE', 'SAGE'),
+                       ('\\rm', ''),
+                       ('backslash','\\'),
+                       ('begin{enumerate}',''),
+                       ('end{enumerate}',''),
+                       ('begin{description}',''),
+                       ('end{description}',''),
+                       ('begin{itemize}',''),
+                       ('end{itemize}',''),
+                       ('begin{verbatim}',''),
+                       ('end{verbatim}',''),
+                       ('note{','NOTE: ')]
 
 def _rmcmd(s, cmd, left='', right=''):
     """
@@ -112,13 +121,20 @@
 itempattern = re.compile(r"\\item\[?([^]]*)\]? *(.*)")
 itemreplace = r"* \1 \2"
 
-def detex(s):
+def detex(s, embedded=False):
     """nodetex
     This strips LaTeX commands from a string; it is used by the
     ``format`` function to process docstrings for display from the
     command line interface.
 
-    INPUT: ``s``, a string.
+    INPUT:
+
+    - ``s`` - string
+    - ``embedded`` - boolean (optional, default False)
+
+    If ``embedded`` is False, then do the replacements in both
+    ``math_substitutes`` and ``nonmath_substitutes``.  If True, then
+    only do ``nonmath_substitutes``.
 
     OUTPUT: string
 
@@ -129,8 +145,10 @@
         'Some math: `n >= k`.  A website: sagemath.org.'
         sage: detex(r'More math: `x \mapsto y`.  {\bf Bold face}.')
         'More math: `x  |-->  y`.  { Bold face}.'
-        sage: detex(r'$a, b, c, \ldots, z$')
-        'a, b, c, ..., z'
+        sage: detex(r'`a, b, c, \ldots, z`')
+        '`a, b, c, ..., z`'
+        sage: detex(r'`a, b, c, \ldots, z`', embedded=True)
+        '`a, b, c, \\\\ldots, z`'
     """
     s = _rmcmd(s, 'url')
     s = _rmcmd(s, 'code')
@@ -142,14 +160,22 @@
     s = _rmcmd(s, 'subsubsection')
     s = _rmcmd(s, 'note', 'NOTE: ', '')
     s = _rmcmd(s, 'emph', '*', '*')
+    s = _rmcmd(s, 'textbf', '*', '*')
 
     s = re.sub(itempattern, itemreplace, s)
-    
-    for a,b in substitutes:
+
+    if not embedded: # not in the notebook
+        for a,b in math_substitutes:  # do math substitutions
+            s = s.replace(a,b)
+        s = s.replace('\\','')        # nuke backslashes
+        s = s.replace('.. math::\n', '')  # get rid of .. math:: directives
+    else:
+        s = s.replace('\\','\\\\')    # double up backslashes for jsMath
+    for a,b in nonmath_substitutes:
         s = s.replace(a,b)
     return s
 
-def format(s):
+def format(s, embedded=False):
     """
     Format Sage documentation ``s`` for viewing with IPython.
 
@@ -157,10 +183,16 @@
     text, and if ``s`` contains a string of the form "<<<obj>>>",
     then it replaces it with the docstring for "obj".
 
-    INPUT: ``s`` - string
+    INPUT:
+
+    - ``s`` - string
+    - ``embedded`` - boolean (optional, default False)
 
     OUTPUT: string
 
+    Set ``embedded`` equal to True if formatting for use in the
+    notebook; this just gets passed as an argument to ``detex``.
+
     EXAMPLES::
 
         sage: from sage.misc.sagedoc import format
@@ -216,9 +248,9 @@
             t = 'Definition: ' + t0 + '\n\n' + t1
             docs.add(obj)
         s = s[:i] + '\n' + t + s[i+6+j:]
-            
+
     if 'nodetex' not in directives:
-        s = detex(s)
+        s = detex(s, embedded=embedded)
     return s
 
 def format_src(s):
diff --git a/sage/misc/sageinspect.py b/sage/misc/sageinspect.py
--- a/sage/misc/sageinspect.py
+++ b/sage/misc/sageinspect.py
@@ -114,6 +114,7 @@
 
 import inspect
 import os
+EMBEDDED_MODE = False
 
 def isclassinstance(obj):
     r"""
@@ -400,6 +401,33 @@
         if s[:4] == 'self':
             s = s[4:]
         s = s.lstrip(',').strip()
+        # for use with typesetting the definition with the notebook:
+        # sometimes s contains "*args" or "**keywds", and the
+        # asterisks confuse ReST/sphinx/docutils, so escape them:
+        # change * to \*, and change ** to \**.
+        if EMBEDDED_MODE:
+            s = s.replace('**', '\\**')  # replace ** with \**
+            t = ''
+            while True:  # replace * with \*
+                i = s.find('*')
+                if i == -1:
+                    break
+                elif i > 0 and s[i-1] == '\\':
+                    if s[i+1] == "*":
+                        t += s[:i+2]
+                        s = s[i+2:]
+                    else:
+                        t += s[:i+1]
+                        s = s[i+1:]
+                    continue 
+                elif i > 0 and s[i-1] == '*':
+                    t += s[:i+1]
+                    s = s[i+1:]
+                    continue
+                else:
+                    t += s[:i] + '\\*'
+                    s = s[i+1:]
+            s = t + s
         return obj_name + '(' + s + ')'
     except (AttributeError, TypeError, ValueError):
         return '%s( [noargspec] )'%obj_name
@@ -439,7 +467,8 @@
 
     if r is None:
         return ''
-    s = sage.misc.sagedoc.format(str(r))
+
+    s = sage.misc.sagedoc.format(str(r), embedded=EMBEDDED_MODE)
 
     # If there is a Cython embedded position, it needs to be stripped
     pos = _extract_embedded_position(s)
diff --git a/sage/server/notebook/cell.py b/sage/server/notebook/cell.py
--- a/sage/server/notebook/cell.py
+++ b/sage/server/notebook/cell.py
@@ -34,7 +34,7 @@
 
 import os, shutil
 
-from   sage.misc.misc import word_wrap
+from   sage.misc.misc import word_wrap, SAGE_ROOT
 from   sage.misc.html import math_parse
 from   sage.misc.preparser import strip_string_literals
 from   sage.misc.package   import is_package_installed
@@ -46,6 +46,12 @@
 else:
     JEDITABLE_TINYMCE = False
 
+# Introspection.  The cache directory is a module-scope variable set
+# in the first call to Cell.set_introspect_html().
+_SAGE_INTROSPECT = None
+import errno, hashlib, time
+from sphinx.application import Sphinx
+
 
 class Cell_generic:
     def is_interactive_cell(self):
@@ -1431,11 +1437,155 @@
     # Introspection #
     #################
     def set_introspect_html(self, html, completing=False):
-        if completing:
+        if html == "" or completing:
             self.__introspect_html = html
+        elif html.find("`") == -1 and html.find("::") == -1:
+            # html doesn't seem to be in ReST format so use docutils
+            # to process the preamble ("**File:**" etc.)  and put
+            # everything else in a <pre> block.
+            i = html.find("**Docstring:**")
+            if i != -1:
+                preamble = html[:i+14]
+                from docutils.core import publish_parts
+                preamble = publish_parts(html[:i+14], writer_name='html')['body']
+                html = html[i+14:]
+            else:
+                preamble = ""
+            self.__introspect_html = '<div class="docstring">' + preamble + '<pre>' + html + '</pre></div>'
         else:
-            html = escape(html).strip()
-            self.__introspect_html = '<pre class="introspection">'+html+'</pre>'
+            # html is in ReST format, so use Sphinx to process it
+            
+            # Set the location of the introspection cache, "permanent"
+            # or temporary.  The former, DOT_SAGE/sage_notebook/doc,
+            # can pool queries from multiple worksheet processes.  The
+            # latter is exclusive to a worksheet's process.  The Sage
+            # cleaner should delete the temporary directory (or
+            # directories) after the notebook server exits.
+            global _SAGE_INTROSPECT
+            if _SAGE_INTROSPECT is None:
+                from sage.misc.misc import DOT_SAGE, tmp_dir
+                # It's important to use os.path.join, instead of +,
+                # because Sphinx counts on normalized paths.  It's also
+                # more portable.
+                std_doc_dir = os.path.join(DOT_SAGE, 'sage_notebook/doc')
+                try:
+                    os.makedirs(std_doc_dir)
+                    _SAGE_INTROSPECT = std_doc_dir
+                except OSError, error:
+                    if error.errno == errno.EEXIST:
+                        if os.access(std_doc_dir, os.R_OK | os.W_OK | os.X_OK):
+                            _SAGE_INTROSPECT = std_doc_dir
+                        else:
+                            _SAGE_INTROSPECT = tmp_dir()
+                    else:
+                        _SAGE_INTROSPECT = tmp_dir()
+                print 'Introspection cache: ', _SAGE_INTROSPECT
+                        
+            # We get a quick checksum of the input.  MD5 admits
+            # collisions, but we're not concerned about such security
+            # issues here.  Of course, if performance permits, we can
+            # choose a more robust hash function.
+            hash = hashlib.md5(html).hexdigest()
+            base_name = os.path.join(_SAGE_INTROSPECT, hash)
+            html_name = base_name + '.html'
+
+            # Multiple processes might try to read/write the target
+            # HTML file simultaneously.  We use a file-based lock.
+            # Since we care only about the target's contents, and
+            # we've configured Sphinx accordingly, we allow multiple
+            # simultaneous instances of Sphinx, as long as their
+            # targets are different.  Systems which don't properly
+            # implement os.O_EXCL may require coarser locking.
+
+            # The Pythonic cross-platform file lock below is adapted
+            # from
+            # http://www.evanfosmark.com/2009/01/cross-platform-file-locking-support-in-python/
+            lock_name = base_name + '.lock'
+
+            # Try to acquire the lock, periodically.  If we time out,
+            # we fall back to plainly formatted documentation.
+            timeout = 0.5
+            delay = 0.05
+            start_time = time.time()
+
+            while True:
+                try:
+                    # This operation is atomic on platforms which
+                    # properly implement os.O_EXCL:
+                    fd_lock = os.open(lock_name, os.O_CREAT | os.O_EXCL | os.O_RDWR)
+                    break;
+                except OSError, err:
+                    if (err.errno != errno.EEXIST) or (time.time() - start_time >= timeout):
+                        plain_html = escape(html).strip()
+                        self.__introspect_html = '<pre class="introspection">' + plain_html + '</pre>'
+                        return
+                    time.sleep(delay)
+
+            # We've acquired the lock.  Use cached HTML or run Sphinx.
+            try:
+                open(html_name, 'r')
+                print 'Found: %s' % html_name
+            except IOError:
+                html = html.replace('\\\\', '\\')
+                rst_name = base_name + '.rst'
+                fd_rst = open(rst_name, 'w')
+                fd_rst.write(html)
+                fd_rst.close()
+
+                # Sphinx setup.  The constructor is Sphinx(srcdir,
+                # confdir, outdir, doctreedir, buildername,
+                # confoverrides, status, warning, freshenv).
+                srcdir = os.path.normpath(_SAGE_INTROSPECT)
+
+                # Note: It's crucial that confdir* contains a
+                # customized conf.py and layout.html.  In particular,
+                # we've disabled index generation and told Sphinx to
+                # output almost exactly the HTML we display.  Sphinx
+                # also pickles its environment in doctreedir, but we
+                # force Sphinx never to load this pickle with
+                # freshenv=True.
+                confdir = os.path.join(SAGE_ROOT, 'devel/sage/doc/introspect')
+                doctreedir = os.path.normpath(base_name)
+                confoverrides = {'html_context' : {}, 'master_doc' : hash}
+
+                # To suppress output, use this:
+#                sphinx_app = Sphinx(srcdir, confdir, srcdir, doctreedir, 'html', confoverrides, None, None, True)
+
+                # For verbose output, use these instead:
+                import sys
+                sphinx_app = Sphinx(srcdir, confdir, srcdir, doctreedir, 'html', confoverrides, sys.stdout, sys.stderr, True)
+
+                # Run Sphinx. The first argument corresponds to
+                # sphinx-build's "write all files" -a flag, which we
+                # set to None.
+                sphinx_app.build(None, [rst_name])
+
+                # We delete .rst files, so future Sphinx runs don't
+                # keep track of them.  We also delete doctrees.
+                try:
+                    os.unlink(rst_name)
+                except OSError:
+                    pass
+                try:
+                    shutil.rmtree(doctreedir)
+                    os.unlink(doctreedir)
+                except OSError:
+                    pass
+
+                print 'Built: %s' % html_name
+            finally:
+                # Contents should be flushed on close().
+                fd_html = open(html_name, 'r')
+                new_html = fd_html.read()
+                fd_html.close()
+
+                # We release the lock and delete the lock file.
+                os.close(fd_lock)
+                os.unlink(lock_name)
+
+                new_html = new_html.replace('<pre>', '<pre class="literal-block">')
+                self.__introspect_html = new_html
+                return
 
     def introspect_html(self):
         if not self.introspect():
diff --git a/sage/server/notebook/css.py b/sage/server/notebook/css.py
--- a/sage/server/notebook/css.py
+++ b/sage/server/notebook/css.py
@@ -293,10 +293,25 @@
 div.introspection {
 }
 
+div.docstring {
+  font-family:arial;
+  background-color: #f1f1f1;
+  color: blue;
+  border: solid 1px black;
+  padding:8px;
+  margin:8px;
+}
+
+pre.literal-block {
+  background-color: #efc;
+  color: blue;    
+}
+
 pre.introspection {
   font-family: monospace;
   font-size:15px;
-  background-color: #efefef;
+  background-color: #f1f1f1;
+  color: blue;
   border: solid 1px black;
   padding:8px;
   margin:8px;
@@ -1635,6 +1650,72 @@
    background-color: #990000;   
 }
 
+
+
+.hll { background-color: #ffffcc }
+.c { color: #408090; font-style: italic } /* Comment */
+.err { border: 1px solid #FF0000 } /* Error */
+.k { color: #007020; font-weight: bold } /* Keyword */
+.o { color: #666666 } /* Operator */
+.cm { color: #408090; font-style: italic } /* Comment.Multiline */
+.cp { color: #007020 } /* Comment.Preproc */
+.c1 { color: #408090; font-style: italic } /* Comment.Single */
+.cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
+.gd { color: #A00000 } /* Generic.Deleted */
+.ge { font-style: italic } /* Generic.Emph */
+.gr { color: #FF0000 } /* Generic.Error */
+.gh { color: #000080; font-weight: bold } /* Generic.Heading */
+.gi { color: #00A000 } /* Generic.Inserted */
+.go { color: #303030 } /* Generic.Output */
+.gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
+.gs { font-weight: bold } /* Generic.Strong */
+.gu { color: #800080; font-weight: bold } /* Generic.Subheading */
+.gt { color: #0040D0 } /* Generic.Traceback */
+.kc { color: #007020; font-weight: bold } /* Keyword.Constant */
+.kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
+.kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
+.kp { color: #007020 } /* Keyword.Pseudo */
+.kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
+.kt { color: #902000 } /* Keyword.Type */
+.m { color: #208050 } /* Literal.Number */
+.s { color: #4070a0 } /* Literal.String */
+.na { color: #4070a0 } /* Name.Attribute */
+.nb { color: #007020 } /* Name.Builtin */
+.nc { color: #0e84b5; font-weight: bold } /* Name.Class */
+.no { color: #60add5 } /* Name.Constant */
+.nd { color: #555555; font-weight: bold } /* Name.Decorator */
+.ni { color: #d55537; font-weight: bold } /* Name.Entity */
+.ne { color: #007020 } /* Name.Exception */
+.nf { color: #06287e } /* Name.Function */
+.nl { color: #002070; font-weight: bold } /* Name.Label */
+.nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
+.nt { color: #062873; font-weight: bold } /* Name.Tag */
+.nv { color: #bb60d5 } /* Name.Variable */
+.ow { color: #007020; font-weight: bold } /* Operator.Word */
+.w { color: #bbbbbb } /* Text.Whitespace */
+.mf { color: #208050 } /* Literal.Number.Float */
+.mh { color: #208050 } /* Literal.Number.Hex */
+.mi { color: #208050 } /* Literal.Number.Integer */
+.mo { color: #208050 } /* Literal.Number.Oct */
+.sb { color: #4070a0 } /* Literal.String.Backtick */
+.sc { color: #4070a0 } /* Literal.String.Char */
+.sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
+.s2 { color: #4070a0 } /* Literal.String.Double */
+.se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
+.sh { color: #4070a0 } /* Literal.String.Heredoc */
+.si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
+.sx { color: #c65d09 } /* Literal.String.Other */
+.sr { color: #235388 } /* Literal.String.Regex */
+.s1 { color: #4070a0 } /* Literal.String.Single */
+.ss { color: #517918 } /* Literal.String.Symbol */
+.bp { color: #007020 } /* Name.Builtin.Pseudo */
+.vc { color: #bb60d5 } /* Name.Variable.Class */
+.vg { color: #bb60d5 } /* Name.Variable.Global */
+.vi { color: #bb60d5 } /* Name.Variable.Instance */
+.il { color: #208050 } /* Literal.Number.Integer.Long */
+
+
+
 """
     if color == 'gmail':
         color1 = '#c3d9ff'
diff --git a/sage/server/notebook/js.py b/sage/server/notebook/js.py
--- a/sage/server/notebook/js.py
+++ b/sage/server/notebook/js.py
@@ -1017,7 +1017,17 @@
             halt_introspection();
             return;
         }
+
         d.innerHTML = introspection_text;
+
+        if (contains_jsmath(introspection_text)) {
+            try {
+                jsMath.ProcessBeforeShowing(d);
+            } catch(e) {
+                text_cell.innerHTML = jsmath_font_msg + d.innerHTML;
+            }
+        }
+
         if(replacing)
             select_replacement_element();
     } else {
@@ -3016,6 +3026,14 @@
         cell_output.innerHTML = '';
         cell_output_nowrap.innerHTML = '';
         cell_output_html.innerHTML = introspect_html;
+        if (contains_jsmath(introspect_html)) {
+            try {
+                jsMath.ProcessBeforeShowing(cell_output_html);
+            } catch(e) {
+                cell_output.innerHTML = jsmath_font_msg + cell_output_html.innerHTML;
+            }
+        }
+
     }
 }
 
diff --git a/sage/server/support.py b/sage/server/support.py
--- a/sage/server/support.py
+++ b/sage/server/support.py
@@ -53,6 +53,7 @@
         sage.structure.sage_object.base=object_directory
     sage.misc.latex.EMBEDDED_MODE = True
     sage.misc.pager.EMBEDDED_MODE = True
+    sage.misc.sageinspect.EMBEDDED_MODE = True
 
     setup_systems(globs)
     sage.misc.session.init(globs)
@@ -188,19 +189,25 @@
     except (AttributeError, NameError, SyntaxError):
         return "No object '%s' currently defined."%obj_name
     s  = ''
+    newline = "\n\n"  # blank line to start new paragraph
     try:
         filename = sageinspect.sage_getfile(obj)
         #i = filename.find('site-packages/sage/')
         #if i == -1:
-        s += 'File:        %s\n'%filename
+        s += '**File:** %s'%filename
+        s += newline
         #else:
         #    file = filename[i+len('site-packages/sage/'):]
         #    s += 'File:        <html><a href="src_browser?%s">%s</a></html>\n'%(file,file)
     except TypeError:
         pass
-    s += 'Type:        %s\n'%type(obj)
-    s += 'Definition:  %s\n'%sageinspect.sage_getdef(obj, obj_name)
-    s += 'Docstring: \n%s\n'%sageinspect.sage_getdoc(obj, obj_name)
+    s += '**Type:** %s'%type(obj)
+    s += newline
+    s += '**Definition:** %s'%sageinspect.sage_getdef(obj, obj_name)
+    s += newline
+    s += '**Docstring:**'
+    s += newline
+    s += sageinspect.sage_getdoc(obj, obj_name)
     return s.rstrip()
 
 def source_code(s, globs, system='sage'):
@@ -226,13 +233,20 @@
             return obj._sage_src_()
         except:
             pass
+        newline = "\n\n"  # blank line to start new paragraph
+        indent = "    "   # indent source code to mark it as a code block
+
         filename = sageinspect.sage_getfile(obj)
         lines, lineno = sageinspect.sage_getsourcelines(obj, is_binary=False)
-        src = ''.join(lines)
-        src = sagedoc.format_src(src)
+        src = indent.join(lines)
+        src = indent + sagedoc.format_src(src)
         if not lineno is None:
-            src = "File: %s\nSource Code (starting at line %s):\n%s"%(filename, lineno, src)
-        return src
+            output = "**File:** %s"%filename
+            output += newline
+            output += "**Source Code** (starting at line %s)::"%lineno
+            output += newline
+            output += src
+        return output
     
     except (TypeError, IndexError), msg:
         print msg
# HG changeset patch
# User Tom Boothby <boothby@u.washington.edu>
# Date 1242707716 25200
# Node ID 124cc31a16eaebdf76435860b30bb9fea095d8df
# Parent  3d7fce9264e936d6978bc1bc3f199b55fea431cd
Suppress noisy sphinx messages.

diff --git a/doc/introspect/builder.py b/doc/introspect/builder.py
deleted file mode 100644
--- a/doc/introspect/builder.py
+++ /dev/null
@@ -1,668 +0,0 @@
-#!/usr/bin/env python
-import os, sys, subprocess, shutil, glob, optparse
-
-#We remove the current directory from sys.path right away
-#so that we import sage from the proper spot
-try:
-    sys.path.remove(os.path.realpath(os.getcwd()))
-except:
-    pass
-
-from sage.misc.cachefunc import cached_method
-
-##########################################
-#                Options                 #
-##########################################
-SAGE_DOC = os.environ['SAGE_DOC']
-LANGUAGES = ['en', 'fr']
-SPHINXOPTS  = ""
-PAPER       = ""
-
-if PAPER == "a4":
-    PAPEROPTS = "-D latex_paper_size=a4"
-elif PAPER == "letter":
-    PAPEROPTS = "-D latex_paper_size=letter"
-else:
-    PAPEROPTS = ""
-
-#Note that this needs to have the doctrees dir    
-ALLSPHINXOPTS   = SPHINXOPTS + " " + PAPEROPTS + " . "
-
-
-##########################################
-#          Utility Functions             #
-##########################################
-def mkdir(path):
-    """
-    Makes the directory at path if it doesn't exist and returns the
-    string path.
-
-    EXAMPLES::
-
-        sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
-        sage: d = tmp_filename(); d
-        '/.../tmp_...'
-        sage: os.path.exists(d)
-        False
-        sage: dd = builder.mkdir(d)
-        sage: d == dd
-        True
-        sage: os.path.exists(d)
-        True
-    """
-    if not os.path.exists(path):
-        os.makedirs(path)
-    return path
-
-def copytree(src, dst, symlinks=False, ignore_errors=False):
-    """
-    Recursively copy a directory tree using copy2().
-
-    The destination directory must not already exist.
-    If exception(s) occur, an Error is raised with a list of reasons.
-
-    If the optional symlinks flag is true, symbolic links in the
-    source tree result in symbolic links in the destination tree; if
-    it is false, the contents of the files pointed to by symbolic
-    links are copied.
-
-    XXX Consider this example code rather than the ultimate tool.
-
-    """
-    names = os.listdir(src)
-    mkdir(dst)
-    errors = []
-    for name in names:
-        srcname = os.path.join(src, name)
-        dstname = os.path.join(dst, name)
-        try:
-            if symlinks and os.path.islink(srcname):
-                linkto = os.readlink(srcname)
-                os.symlink(linkto, dstname)
-            elif os.path.isdir(srcname):
-                copytree(srcname, dstname, symlinks)
-            else:
-                shutil.copy2(srcname, dstname)
-            # XXX What about devices, sockets etc.?
-        except (IOError, os.error), why:
-            errors.append((srcname, dstname, str(why)))
-        # catch the Error from the recursive copytree so that we can
-        # continue with other files
-        except shutil.Error, err:
-            errors.extend(err.args[0])
-    try:
-        shutil.copystat(src, dst)
-    except OSError, why:
-        errors.extend((src, dst, str(why)))
-    if errors and not ignore_errors:
-        raise shutil.Error, errors
-
-
-
-##########################################
-#             Builders                   #
-##########################################
-def builder_helper(type):
-    """
-    Returns a function which builds the documentation for
-    output type type.
-    """
-    def f(self):
-        output_dir = self._output_dir(type)
-        os.chdir(self.dir)
-
-        build_command = 'sphinx-build'
-        build_command += ' -b %s -d %s %s %s'%(type, self._doctrees_dir(),
-                                               ALLSPHINXOPTS, output_dir)
-        print build_command
-        subprocess.call(build_command, shell=True)
-
-        print "Build finished.  The built documents can be found in %s"%output_dir
-        
-    f.is_output_format = True
-    return f
-        
-
-class DocBuilder(object):
-    def __init__(self, name, lang='en'):
-        """
-        INPUT:
-            
-        - ``name`` - the name of a subdirectory in SAGE_DOC, such as
-          'tutorial' or 'bordeaux_2008'
-
-        - ``lang`` - (default "en") the language of the document.
-        """
-        if '/' in name:
-            lang, name = name.split(os.path.sep)
-        self.name = name
-        self.lang = lang
-        self.dir = os.path.join(SAGE_DOC, lang, name)
-
-        #Make sure the .static and .templates directories are there
-        mkdir(os.path.join(self.dir, "static"))
-        mkdir(os.path.join(self.dir, "templates"))
-
-    def _output_dir(self, type):
-        """
-        Returns the directory where the output of type type is stored.
-        If the directory does not exist, then it will automatically be
-        created.
-
-        EXAMPLES::
-
-            sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
-            sage: b = builder.DocBuilder('tutorial')
-            sage: b._output_dir('html')
-            '.../devel/sage/doc/output/html/en/tutorial'
-        """
-        return mkdir(os.path.join(SAGE_DOC, "output", type, self.lang, self.name))
-
-    def _doctrees_dir(self):
-        """
-        Returns the directory where the doctrees are stored.  If the
-        directory does not exist, then it will automatically be
-        created.
-
-        EXAMPLES::
-
-            sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
-            sage: b = builder.DocBuilder('tutorial')
-            sage: b._doctrees_dir()
-            '.../devel/sage/doc/output/doctrees/en/tutorial'
-        """
-        return mkdir(os.path.join(SAGE_DOC, "output", 'doctrees', self.lang, self.name))
-
-    def _output_formats(self):
-        """
-        Returns a list of the possible output formats.
-
-        EXAMPLES::
-
-            sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
-            sage: b = builder.DocBuilder('tutorial')
-            sage: b._output_formats()
-            ['changes', 'html', 'htmlhelp', 'json', 'latex', 'linkcheck', 'pickle', 'web']
-
-        """
-        #Go through all the attributes of self and check to
-        #see which ones have an 'is_output_format' attribute.  These
-        #are the ones created with builder_helper.
-        output_formats = []
-        for attr in dir(self):
-            if hasattr(getattr(self, attr), 'is_output_format'):
-                output_formats.append(attr)
-        output_formats.sort()
-        return output_formats
-
-    def pdf(self):
-        """
-        Builds the PDF files for this document.  This is done by first
-        (re)-building the LaTeX output, going into that LaTeX
-        directory, and running 'make all-pdf' there.
-
-        EXAMPLES::
-
-            sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
-            sage: b = builder.DocBuilder('tutorial')
-            sage: b.pdf() #not tested
-        """
-        self.latex()
-        os.chdir(self._output_dir('latex'))
-        subprocess.call('make all-pdf', shell=True)
-
-        pdf_dir = self._output_dir('pdf')
-        for pdf_file in glob.glob('*.pdf'):
-            shutil.move(pdf_file, os.path.join(pdf_dir, pdf_file))
-
-        print "Build finished.  The built documents can be found in %s"%pdf_dir              
-
-    def clean(self, *args):
-        """
-        """
-        import shutil
-        shutil.rmtree(self._doctrees_dir())
-        output_formats = list(args) if args else self._output_formats()
-        for format in output_formats:
-            shutil.rmtree(self._output_dir(format), ignore_errors=True)
-        
-    html = builder_helper('html')
-    pickle = builder_helper('pickle')
-    web = pickle
-    json = builder_helper('json')                       
-    htmlhelp = builder_helper('htmlhelp')
-    latex = builder_helper('latex')
-    changes = builder_helper('changes')
-    linkcheck = builder_helper('linkcheck')
-
-class AllBuilder(object):
-    """
-    A class used to build all of the documentation.
-    """
-    def __getattr__(self, attr):
-        """
-        For any attributes not explicitly defined, we just go through
-        all of the documents and call their attr.  For example,
-        'AllBuilder().json()' will go through all of the documents
-        and call the json() method on their builders.
-        """
-        from functools import partial
-        return partial(self._wrapper, attr)
-
-    def _wrapper(self, name, *args, **kwds):
-        """
-        This is the function which goes through all of the documents
-        and does the actual building.
-        """
-        for document in self.get_all_documents():
-            getattr(get_builder(document), name)(*args, **kwds)
-
-    def get_all_documents(self):
-        """
-        Returns a list of all of the documents. A document is a directory within one of 
-        the language subdirectories of SAGE_DOC specified by the global LANGUAGES
-        variable.
-
-        EXAMPLES::
-
-            sage: import os, sys; sys.path.append(os.environ['SAGE_DOC']+'/common/'); import builder
-            sage: documents = builder.AllBuilder().get_all_documents()
-            sage: 'en/tutorial' in documents
-            True
-        """
-        documents = []
-        for lang in LANGUAGES:
-            for document in os.listdir(os.path.join(SAGE_DOC, lang)):
-                documents.append(os.path.join(lang, document))
-        return documents
-
-class WebsiteBuilder(DocBuilder):
-    def html(self):
-        """
-        After we've finished building the website index page, we copy
-        everything one directory up.
-        """
-        DocBuilder.html(self)
-        html_output_dir = self._output_dir('html')
-        copytree(html_output_dir,
-                 os.path.realpath(os.path.join(html_output_dir, '..')),
-                 ignore_errors=False)
-
-    def clean(self):
-        """
-        When we clean the output for the website index, we need to
-        remove all of the HTML that were placed in the parent
-        directory.
-        """
-        html_output_dir = self._output_dir('html')
-        parent_dir = os.path.realpath(os.path.join(html_output_dir, '..'))
-        for filename in os.listdir(html_output_dir):
-            parent_filename = os.path.join(parent_dir, filename)
-            if not os.path.exists(parent_filename):
-                continue
-            if os.path.isdir(parent_filename):
-                shutil.rmtree(parent_filename, ignore_errors=True)
-            else:
-                os.unlink(parent_filename)
-
-        DocBuilder.clean(self)
-
-class ReferenceBuilder(DocBuilder):
-    """
-    This the class used to build the reference manual.  It is
-    resposible for making sure the auto generated ReST files for the
-    Sage library are up to date.
-
-    When building any output, we must first go through and check
-    to see if we need to update any of the autogenerated ReST
-    files.  There are two cases where this would happen:
-
-    1. A new module gets added to one of the toctrees.
-    
-    2. The actual module gets updated and possibly contains a new
-       title.
-    """
-    def __init__(self, *args, **kwds):
-        DocBuilder.__init__(self, *args, **kwds)
-        self._wrap_builder_helpers()
-
-    def _wrap_builder_helpers(self):
-        from functools import partial, update_wrapper
-        for attr in dir(self):
-            if hasattr(getattr(self, attr), 'is_output_format'):
-                f = partial(self._wrapper, attr)
-                f.is_output_format = True
-                update_wrapper(f, getattr(self, attr))
-                setattr(self, attr, f)
-    
-    def _wrapper(self, build_type, *args, **kwds):
-        """
-        This is the wrapper around the builder_helper methods that
-        goes through and makes sure things are up to date.
-        """
-        #Write the .rst files for newly included modules
-        for module_name in self.get_newly_included_modules(save=True):
-            self.write_auto_rest_file(module_name)
-
-        #Update the .rst files for modified Python modules
-        for module_name in self.get_modified_modules():
-            self.write_auto_rest_file(module_name.replace(os.path.sep, '.'))
-
-        #Copy over the custom .rst files from _sage
-        _sage = os.path.join(self.dir, '_sage')
-        if os.path.exists(_sage):
-            copytree(_sage, os.path.join(self.dir, 'sage'))
-                
-        getattr(DocBuilder, build_type)(self, *args, **kwds)
-    
-    def cache_filename(self):
-        """
-        Returns the filename where the pickle of the dictionary of
-        already generated .rst files is stored.
-        """
-        return os.path.join(self._doctrees_dir(), 'reference.pickle')
-
-    @cached_method
-    def get_cache(self):
-        """
-        Retreive the cache of already generated .rst files.  If it
-        doesn't exist, then we just return an empty dictionary.
-        """
-        filename = self.cache_filename()
-        if not os.path.exists(filename):
-            return {}
-
-        import cPickle
-        file = open(self.cache_filename(), 'rb')
-        cache = cPickle.load(file)
-        file.close()
-        return cache
-        
-
-    def save_cache(self):
-        """
-        Save the cache of already generated .rst files.
-        """
-        import cPickle
-        file = open(self.cache_filename(), 'wb')
-        cPickle.dump(self.get_cache(), file)
-        file.close()
-
-    def get_sphinx_environment(self):
-        """
-        Returns the Sphinx environment for this project.
-        """
-        from sphinx.environment import BuildEnvironment
-        class Foo(object):
-            pass
-        config = Foo()
-        config.values = []
-
-        env_pickle = os.path.join(self._doctrees_dir(), 'environment.pickle')
-        try:
-            return BuildEnvironment.frompickle(config, env_pickle)
-        except IOError:
-            pass
-                                           
-    def get_modified_modules(self):
-        """
-        Returns an iterator for all the modules that have been modified
-        since the docuementation was last built.
-        """
-        env = self.get_sphinx_environment()
-        if env is None:
-            return
-        added, changed, removed = env.get_outdated_files(False)
-        for name in changed:
-            if name.startswith('sage'):
-                yield name
-
-    def print_modified_modules(self):
-        """
-        Prints a list of all the modules that have been modified since
-        the documentation was last built.
-        """
-        for module_name in self.get_modified_modules():
-            print module_name
-
-    def get_all_rst_files(self, exclude_sage=True):
-        """
-        Returns an iterator for all rst files which are not
-        autogenerated.
-        """
-        for directory, subdirs, files in os.walk(self.dir):
-            if exclude_sage and directory.startswith(os.path.join(self.dir, 'sage')):
-                continue
-            for filename in files:
-                if not filename.endswith('.rst'):
-                    continue
-                yield os.path.join(directory, filename)
-
-    def get_all_included_modules(self):
-        """
-        Returns an iterator for all modules which are included in the
-        reference manual.
-        """
-        for filename in self.get_all_rst_files():
-            for module in self.get_modules(filename):
-                yield module
-
-    def get_newly_included_modules(self, save=False):
-        """
-        Returns an iterator for all modules that appear in the
-        toctrees that don't appear in the cache.
-        """
-        cache = self.get_cache()
-        new_modules = []
-        for module in self.get_all_included_modules():
-            if module not in cache:
-                cache[module] = True
-                yield module
-        if save:
-            self.save_cache()
-
-    def print_newly_included_modules(self):
-        """
-        Prints all of the modules that appear in the toctrees that
-        don't appear in the cache.
-        """
-        for module_name in self.get_newly_included_modules():
-            print module_name
-
-    def get_modules(self, filename):
-        """
-        Given a filename for a .rst file, return an iterator for
-        all of the autogenerated rst files that it includes.
-        """
-        #Create the regular expression used to detect an autogenerated file
-        import re
-        auto_re = re.compile('^\s*(..\/)*(sage\/[\w\/]*)\s*$')
-
-        #Read the lines
-        f = open(filename)
-        lines = f.readlines()
-        f.close()
-
-        for line in lines:
-            match = auto_re.match(line)
-            if match:
-                yield match.group(2).replace(os.path.sep, '.')
-                
-    def get_module_docstring_title(self, module_name):
-        """
-        Returns the title of the module from its docstring.
-        """
-        #Try to import the module
-        try:
-            import sage.all
-            __import__(module_name)
-        except ImportError, err:
-            raise
-            print "Warning: could not import %s"%module_name
-            print err
-            return "UNABLE TO IMPORT MODULE"
-        module = sys.modules[module_name]
-
-        #Get the docstring
-        doc = module.__doc__
-        if doc is None:
-            doc = module.doc if hasattr(module, 'doc') else ""
-
-        #Extract the title
-        i = doc.find('\n')
-        if i != -1:
-            return doc[i+1:].lstrip().splitlines()[0]
-        else:
-            return doc
-
-    def write_auto_rest_file(self, module_name):
-        """
-        Writes the autogenerated .rst file for module_name.
-        """
-        if not module_name.startswith('sage'):
-            return
-        filename = self.dir + os.path.sep + module_name.replace('.',os.path.sep) + '.rst'
-        mkdir(os.path.dirname(filename))
-        
-        outfile = open(filename, 'w')
-
-        title = self.get_module_docstring_title(module_name)
-
-        if title == '':
-            print "WARNING: Missing title for", module_name
-            title = "MISSING TITLE"
-
-        outfile.write(title + '\n')
-        outfile.write('='*len(title) + "\n\n")
-        outfile.write('.. This file has been autogenerated.\n\n')
-        automodule = '.. automodule:: %s\n   :members:\n   :undoc-members:\n\n'
-        outfile.write(automodule%module_name)
-
-        outfile.close()
-
-    def clean_auto(self):
-        """
-        Remove the cache file for the autogenerated files as well as
-        the files themselves.
-        """
-        if os.path.exists(self.cache_filename()):
-            os.unlink(self.cache_filename())
-
-        import shutil
-        shutil.rmtree(self.dir + '/sage')
-
-    def get_unincluded_modules(self):
-        """
-        Returns an iterator for all the modules in the Sage library
-        which are not included in the reference manual.
-        """
-        #Make a dictionary of the included modules
-        included_modules = {}
-        for module_name in self.get_all_included_modules():
-            included_modules[module_name] = True
-        
-        base_path = os.path.join(os.environ['SAGE_ROOT'], 'devel', 'sage', 'sage')
-        for directory, subdirs, files in os.walk(base_path):
-            for filename in files:
-                if not (filename.endswith('.py') or
-                        filename.endswith('.pyx')):
-                    continue
-                
-                path = os.path.join(directory, filename)
-
-                #Create the module name
-                module_name = path[len(base_path):].replace(os.path.sep, '.')
-                module_name = 'sage' + module_name
-                module_name = module_name[:-4] if module_name.endswith('pyx') else module_name[:-3]
-
-                #Exclude some ones  -- we don't want init the manual
-                if module_name.endswith('__init__') or module_name.endswith('all'):
-                    continue
-
-                if module_name not in included_modules:
-                    yield module_name
-                
-    def print_unincluded_modules(self):
-        """
-        Prints all of the modules which are not included in the Sage
-        reference manual.
-        """
-        for module_name in self.get_unincluded_modules():
-            print module_name
-
-    def print_included_modules(self):
-        """
-        Prints all of the modules that are included in the Sage reference
-        manual.
-        """
-        for module_name in self.get_all_included_modules():
-            print module_name
-
-        
-
-def get_builder(name):
-    """
-    Returns a either a AllBuilder or DocBuilder object depending
-    on whether ``name`` is 'all' or not.  These are the objects
-    which do all the real work in building the documentation.
-    """
-    if name == 'all':
-        return AllBuilder()
-    elif name.endswith('reference'):
-        return ReferenceBuilder(name)
-    elif name.endswith('website'):
-        return WebsiteBuilder(name)
-    else:
-        return DocBuilder(name)
-	      
-
-def help_message():
-    """
-    Returns the help message. 
-    """
-    all_b = AllBuilder()
-    docs = all_b.get_all_documents()
-    docs = [(d[3:] if d[0:3] == 'en/' else d) for d in docs]
-    tut_b = DocBuilder('en/tutorial')
-    formats = tut_b._output_formats()
-    formats.remove('html')
-    help = "Usage: sage -docbuild {document} {format}\n"
-    help += "Where {document} is one of:\n    "
-    help += "\n    ".join(docs)
-    help += "\nor 'all' for all documents, and {format} is one of:\n    "
-    help += 'html, pdf, ' + ', '.join(formats)
-    help += "\n"
-    help += "When building the reference manual, there are several additional\n"
-    help += "values for {format}:\n"
-    help += "    print_modified_modules: list modules modified since the documentation\n"
-    help += "         was last built\n"
-    help += "    print_newly_included_modules: list modules added to the\n"
-    help += "         documentation since it was last built\n"
-    help += "    print_unincluded_modules: list modules not included in the documentation\n"
-    help += "    print_included_modules: list modules included in the documentation\n"
-    print help
-
-
-parser = optparse.OptionParser(usage="usage: sage -docbuild [options] name type")
-parser.add_option("--jsmath", action="store_true",
-                  help="render math using jsMath")
-parser.print_help = help_message
-
-if __name__ == '__main__':
-    options, args = parser.parse_args()
-
-    if options.jsmath:
-        os.environ['SAGE_DOC_JSMATH'] = "True"
-
-    #Get the name of the document we are trying to build
-    try:
-        name, type = args
-    except ValueError:
-        print "You must specify the document name and the output format"
-        sys.exit(0)
-   
-    #Make sure common/static exists
-    mkdir(os.path.join(SAGE_DOC, 'common', 'static'))
-
-    #Get the builder and build
-    getattr(get_builder(name), type)()
diff --git a/sage/server/notebook/cell.py b/sage/server/notebook/cell.py
--- a/sage/server/notebook/cell.py
+++ b/sage/server/notebook/cell.py
@@ -1549,11 +1549,11 @@
                 confoverrides = {'html_context' : {}, 'master_doc' : hash}
 
                 # To suppress output, use this:
-#                sphinx_app = Sphinx(srcdir, confdir, srcdir, doctreedir, 'html', confoverrides, None, None, True)
+                sphinx_app = Sphinx(srcdir, confdir, srcdir, doctreedir, 'html', confoverrides, None, None, True)
 
                 # For verbose output, use these instead:
                 import sys
-                sphinx_app = Sphinx(srcdir, confdir, srcdir, doctreedir, 'html', confoverrides, sys.stdout, sys.stderr, True)
+#                sphinx_app = Sphinx(srcdir, confdir, srcdir, doctreedir, 'html', confoverrides, sys.stdout, sys.stderr, True)
 
                 # Run Sphinx. The first argument corresponds to
                 # sphinx-build's "write all files" -a flag, which we
diff --git a/sage/server/notebook/css.py b/sage/server/notebook/css.py
--- a/sage/server/notebook/css.py
+++ b/sage/server/notebook/css.py
@@ -1652,6 +1652,8 @@
 
 
 
+/* These have been scraped directly from pygment. */
+
 .hll { background-color: #ffffcc }
 .c { color: #408090; font-style: italic } /* Comment */
 .err { border: 1px solid #FF0000 } /* Error */
@@ -1714,7 +1716,7 @@
 .vi { color: #bb60d5 } /* Name.Variable.Instance */
 .il { color: #208050 } /* Literal.Number.Integer.Long */
 
-
+/* end stuff scraped from pygment */
 
 """
     if color == 'gmail':
# HG changeset patch
# User Mitesh Patel <qed777@gmail.com>
# Date 1242728269 25200
# Node ID 1eacea743efa874ac44b1d67b0e0f074ecd8066b
# Parent  124cc31a16eaebdf76435860b30bb9fea095d8df
Move introspect config to doc/en/introspect, make relative to doc/common.

diff --git a/doc/en/introspect/conf.py b/doc/en/introspect/conf.py
new file mode 100644
--- /dev/null
+++ b/doc/en/introspect/conf.py
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+# Sage introspection build configuration file.
+# See sage.server.notebook.cell.set_introspect_html() for details.
+
+import sys, os
+sys.path.append(os.environ['SAGE_DOC'])
+from common.conf import *
+
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.jsmath']
+
+templates_path = ['templates']
+html_static_path = ['static']
+
+html_use_modindex = False
+html_use_index = False
+html_split_index = False
+html_copy_source = False
diff --git a/doc/en/introspect/static/.empty b/doc/en/introspect/static/.empty
new file mode 100644
--- /dev/null
+++ b/doc/en/introspect/static/.empty
@@ -0,0 +1,1 @@
+ 
\ No newline at end of file
diff --git a/doc/en/introspect/templates/layout.html b/doc/en/introspect/templates/layout.html
new file mode 100644
--- /dev/null
+++ b/doc/en/introspect/templates/layout.html
@@ -0,0 +1,3 @@
+<div class="docstring">
+    {% block body %} {% endblock %}
+</div>
diff --git a/doc/introspect/__init__.py b/doc/introspect/__init__.py
deleted file mode 100644
--- a/doc/introspect/__init__.py
+++ /dev/null
@@ -1,1 +0,0 @@
- 
diff --git a/doc/introspect/conf.py b/doc/introspect/conf.py
deleted file mode 100644
--- a/doc/introspect/conf.py
+++ /dev/null
@@ -1,226 +0,0 @@
-import sys, os
-SAGE_DOC = os.environ['SAGE_ROOT'] + '/devel/sage/doc'
-
-# If your extensions are in another directory, add it here. If the directory
-# is relative to the documentation root, use os.path.abspath to make it
-# absolute, like shown here.
-#sys.path.append(os.path.abspath('.'))
-
-# General configuration
-# ---------------------
-
-# Add any Sphinx extension module names here, as strings. They can be extensions
-# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.autodoc', 'sphinx.ext.jsmath']
-
-jsmath_path = '/javascript_local/jsmath/easy/load.js'
-
-# Add any paths that contain templates here, relative to this directory.
-templates_path = [SAGE_DOC + '/introspect/templates', 'templates']
-
-# The suffix of source filenames.
-source_suffix = '.rst'
-
-# The master toctree document.
-master_doc = 'index'
-
-# General information about the project.
-project = u""
-copyright = u'2008, The Sage Group'
-
-# The version info for the project you're documenting, acts as replacement for
-# |version| and |release|, also used in various other places throughout the
-# built documents.
-#
-# The short X.Y version.
-# from sage.version import version
-# release = version
-
-#version = '3.1.2'
-# The full version, including alpha/beta/rc tags.
-#release = '3.1.2'
-
-# The language for content autogenerated by Sphinx. Refer to documentation
-# for a list of supported languages.
-#language = None
-
-# There are two options for replacing |today|: either, you set today to some
-# non-false value, then it is used:
-#today = ''
-# Else, today_fmt is used as the format for a strftime call.
-#today_fmt = '%B %d, %Y'
-
-# List of documents that shouldn't be included in the build.
-#unused_docs = []
-
-# List of directories, relative to source directory, that shouldn't be searched
-# for source files.
-exclude_trees = ['.build']
-
-# The reST default role (used for this markup: `text`) to use for all documents.
-default_role = 'math'
-
-# If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
-
-# If true, the current module name will be prepended to all description
-# unit titles (such as .. function::).
-#add_module_names = True
-
-# If true, sectionauthor and moduleauthor directives will be shown in the
-# output. They are ignored by default.
-#show_authors = False
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
-
-
-# Options for HTML output
-# -----------------------
-
-# The style sheet to use for HTML and HTML Help pages. A file of that name
-# must exist either in Sphinx' static/ path, or in one of the custom paths
-# given in html_static_path.
-html_style = 'default.css'
-
-# The name for this set of Sphinx documents.  If None, it defaults to
-# "<project> v<release> documentation".
-#html_title = None
-
-# A shorter title for the navigation bar.  Default is the same as html_title.
-#html_short_title = None
-
-# The name of an image file (within the static path) to place at the top of
-# the sidebar.
-#html_logo = 'sagelogo-word.ico'
-
-# The name of an image file (within the static path) to use as favicon of the
-# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
-# pixels large.
-# html_favicon = 'sageicon.png'
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = [SAGE_DOC +'/introspect/static', 'static']
-
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
-
-# If true, SmartyPants will be used to convert quotes and dashes to
-# typographically correct entities.
-#html_use_smartypants = True
-
-# Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
-
-# Additional templates that should be rendered to pages, maps page names to
-# template names.
-#html_additional_pages = {}
-
-# If false, no module index is generated.
-html_use_modindex = False
-
-# If false, no index is generated.
-html_use_index = False
-
-# If true, the index is split into individual pages for each letter.
-#html_split_index = True
-
-# If true, the reST sources are included in the HTML build as _sources/<name>.
-html_copy_source = False
-
-# If true, an OpenSearch description file will be output, and all pages will
-# contain a <link> tag referring to it.  The value of this option must be the
-# base URL from which the finished HTML is served.
-#html_use_opensearch = ''
-
-# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = ''
-
-# Output file base name for HTML help builder.
-#htmlhelp_basename = ''
-
-
-# Options for LaTeX output
-# ------------------------
-
-# The paper size ('letter' or 'a4').
-#latex_paper_size = 'letter'
-
-# The font size ('10pt', '11pt' or '12pt').
-#latex_font_size = '10pt'
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title, author, document class [howto/manual]).
-#latex_documents = []
-
-# The name of an image file (relative to this directory) to place at the top of
-# the title page.
-#latex_logo = 'sagelogo-word.png'
-
-# For "manual" documents, if this is true, then toplevel headings are parts,
-# not chapters.
-#latex_use_parts = False
-
-# Additional stuff for the LaTeX preamble.
-#latex_preamble = ''
-#latex_preamble = '\usepackage{amsmath}\n\usepackage{amsfonts}\n'
-
-# Documents to append as an appendix to all manuals.
-#latex_appendices = []
-
-# If false, no module index is generated.
-#latex_use_modindex = True
-
-
-#####################################################
-
-def process_docstring_aliases(app, what, name, obj, options, docstringlines):
-    """
-    Change the docstrings for aliases to point to the original object.
-    """
-    basename = name.rpartition('.')[2]
-    if hasattr(obj, '__name__') and obj.__name__ != basename:
-        docstringlines[:] = ['See :obj:`%s`.' % name]
-
-def process_docstring_cython(app, what, name, obj, options, docstringlines):
-    """
-    Remove Cython's filename and location embedding.
-    """
-    if len(docstringlines) <= 1:
-        return
-
-    first_line = docstringlines[0]
-    if first_line.startswith('File:') and '(starting at' in first_line:
-        #Remove the first two lines
-        docstringlines.pop(0)
-        docstringlines.pop(0)
-
-def process_docstring_module_title(app, what, name, obj, options, docstringlines):
-    """
-    Removes the first line from the beginning of the module's docstring.  This 
-    corresponds to the title of the module's documentation page.
-    """
-    if what != "module":
-        return
-
-    #Remove any additional blank lines at the beginning
-    title_removed = False
-    while len(docstringlines) > 1 and not title_removed:
-        if docstringlines[0].strip() != "":
-            title_removed = True
-        docstringlines.pop(0)
-
-    #Remove any additional blank lines at the beginning
-    while len(docstringlines) > 1:
-        if docstringlines[0].strip() == "":
-            docstringlines.pop(0)
-        else:
-            break
-
-        
-def setup(app):
-    app.connect('autodoc-process-docstring', process_docstring_cython)
-    app.connect('autodoc-process-docstring', process_docstring_module_title)
diff --git a/doc/introspect/static/.empty b/doc/introspect/static/.empty
deleted file mode 100644
--- a/doc/introspect/static/.empty
+++ /dev/null
@@ -1,1 +0,0 @@
- 
\ No newline at end of file
diff --git a/doc/introspect/templates/layout.html b/doc/introspect/templates/layout.html
deleted file mode 100644
--- a/doc/introspect/templates/layout.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<div class="docstring">
-    {% block body %} {% endblock %}
-</div>
diff --git a/sage/server/notebook/cell.py b/sage/server/notebook/cell.py
--- a/sage/server/notebook/cell.py
+++ b/sage/server/notebook/cell.py
@@ -34,7 +34,7 @@
 
 import os, shutil
 
-from   sage.misc.misc import word_wrap, SAGE_ROOT
+from   sage.misc.misc import word_wrap, SAGE_DOC
 from   sage.misc.html import math_parse
 from   sage.misc.preparser import strip_string_literals
 from   sage.misc.package   import is_package_installed
@@ -1544,7 +1544,7 @@
                 # also pickles its environment in doctreedir, but we
                 # force Sphinx never to load this pickle with
                 # freshenv=True.
-                confdir = os.path.join(SAGE_ROOT, 'devel/sage/doc/introspect')
+                confdir = os.path.join(SAGE_DOC, 'en/introspect')
                 doctreedir = os.path.normpath(base_name)
                 confoverrides = {'html_context' : {}, 'master_doc' : hash}
 
@@ -1552,7 +1552,7 @@
                 sphinx_app = Sphinx(srcdir, confdir, srcdir, doctreedir, 'html', confoverrides, None, None, True)
 
                 # For verbose output, use these instead:
-                import sys
+#                import sys
 #                sphinx_app = Sphinx(srcdir, confdir, srcdir, doctreedir, 'html', confoverrides, sys.stdout, sys.stderr, True)
 
                 # Run Sphinx. The first argument corresponds to
