Ticket #5653: trac_5653_pretty_docstrings_v7.patch

File trac_5653_pretty_docstrings_v7.patch, 25.1 KB (added by mpatel, 12 years ago)

Re-base against v4.1 + #6307's "bis" and "reviewer" patches. Apply only this patch.

  • new file doc/en/introspect/__init__.py

    # HG changeset patch
    # User Mitesh Patel <qed777@gmail.com>
    # Date 1247982006 25200
    # Node ID 6cf0add609d669c637cc34ca60d5885fc8aa130e
    # Parent  96fa87f89635aae879b7942047355011f4dfacee
    #5653, notebook docstrings using HTML and jsMath
    
    diff --git a/doc/en/introspect/__init__.py b/doc/en/introspect/__init__.py
    new file mode 100644
    - +  
     1 
  • new file doc/en/introspect/conf.py

    diff --git a/doc/en/introspect/conf.py b/doc/en/introspect/conf.py
    new file mode 100644
    - +  
     1# -*- coding: utf-8 -*-
     2# Sage introspection build configuration file.
     3# See sage.server.notebook.cell.set_introspect_html() for details.
     4
     5import sys, os
     6sys.path.append(os.environ['SAGE_DOC'])
     7from common.conf import *
     8
     9extensions = ['sphinx.ext.autodoc', 'sphinx.ext.jsmath']
     10
     11templates_path = ['templates']
     12html_static_path = ['static']
     13
     14html_use_modindex = False
     15html_use_index = False
     16html_split_index = False
     17html_copy_source = False
  • new file doc/en/introspect/static/empty

    diff --git a/doc/en/introspect/static/empty b/doc/en/introspect/static/empty
    new file mode 100644
    - +  
     1
  • new file doc/en/introspect/templates/layout.html

    diff --git a/doc/en/introspect/templates/layout.html b/doc/en/introspect/templates/layout.html
    new file mode 100644
    - +  
     1<div class="docstring">
     2    {% block body %} {% endblock %}
     3</div>
  • sage/misc/sagedoc.py

    diff --git a/sage/misc/sagedoc.py b/sage/misc/sagedoc.py
    a b AUTHORS: 
    3030import os, re
    3131from subprocess import Popen, PIPE
    3232
    33 #('\\item', '*'), \
    34 substitutes = [('\\_','_'),\
    35                ('\\item', '* '), \
    36                ('\\to', '-->'), \
    37                ('<BLANKLINE>',''), \
    38                ('\\leq', '<='), \
    39                ('\\geq', '>='), \
    40                ('\\le', '<='), \
    41                ('\\ge', '>='), \
    42                ('\\bf', ''),\
    43                ('\\sage', 'SAGE'), \
    44                ('\\SAGE', 'SAGE'), \
    45                ('\\rm', ''), \
    46                ('cdots', '...'), \
    47                ('\\cdot', ' *'), \
    48                ('$',''), ('\\',''), ('backslash','\\'), \
    49                ('begin{enumerate}',''), ('end{enumerate}',''), \
    50                ('begin{description}',''), ('end{description}',''), \
    51                ('begin{itemize}',''), ('end{itemize}',''), \
    52                ('begin{verbatim}',''), ('end{verbatim}',''), \
    53                ('mapsto', ' |--> '), \
    54                ('ldots', '...'), ('note{','NOTE: ')]
    55 
     33# two kinds of substitutions: math, which should only be done on the
     34# command line -- in the notebook, these should instead by taken care
     35# of by jsMath -- and nonmath, which should be done always.
     36math_substitutes = [('\\to', '-->'),
     37                    ('\\leq', '<='),
     38                    ('\\geq', '>='),
     39                    ('\\le', '<='),
     40                    ('\\ge', '>='),
     41                    ('cdots', '...'),
     42                    ('\\cdot', ' *'),
     43                    (' \\times', ' x'),
     44                    ('\\times', ' x'),
     45                    ('backslash','\\'),
     46                    ('mapsto', ' |--> '),
     47                    ('ldots', '...')]
     48nonmath_substitutes = [('\\_','_'),
     49                       ('\\item', '* '),
     50                       ('<BLANKLINE>',''),
     51                       ('\\bf', ''),
     52                       ('\\sage', 'SAGE'),
     53                       ('\\SAGE', 'SAGE'),
     54                       ('\\rm', ''),
     55                       ('backslash','\\'),
     56                       ('begin{enumerate}',''),
     57                       ('end{enumerate}',''),
     58                       ('begin{description}',''),
     59                       ('end{description}',''),
     60                       ('begin{itemize}',''),
     61                       ('end{itemize}',''),
     62                       ('begin{verbatim}',''),
     63                       ('end{verbatim}',''),
     64                       ('note{','NOTE: ')]
    5665
    5766def _rmcmd(s, cmd, left='', right=''):
    5867    """
    import re 
    122131itempattern = re.compile(r"\\item\[?([^]]*)\]? *(.*)")
    123132itemreplace = r"* \1 \2"
    124133
    125 def detex(s):
     134def detex(s, embedded=False):
    126135    r"""nodetex
    127136    This strips LaTeX commands from a string; it is used by the
    128137    ``format`` function to process docstrings for display from the
    129138    command line interface.
    130139
    131     INPUT: ``s``, a string.
     140    INPUT:
     141
     142    - ``s`` - string
     143    - ``embedded`` - boolean (optional, default False)
     144
     145    If ``embedded`` is False, then do the replacements in both
     146    ``math_substitutes`` and ``nonmath_substitutes``.  If True, then
     147    only do ``nonmath_substitutes``.
    132148
    133149    OUTPUT: string
    134150
    def detex(s): 
    139155        'Some math: `n >= k`.  A website: sagemath.org.'
    140156        sage: detex(r'More math: `x \mapsto y`.  {\bf Bold face}.')
    141157        'More math: `x  |-->  y`.  { Bold face}.'
    142         sage: detex(r'$a, b, c, \ldots, z$')
    143         'a, b, c, ..., z'
     158        sage: detex(r'`a, b, c, \ldots, z`')
     159        '`a, b, c, ..., z`'
     160        sage: detex(r'`a, b, c, \ldots, z`', embedded=True)
     161        '`a, b, c, \\\\ldots, z`'
    144162    """
    145163    s = _rmcmd(s, 'url')
    146164    s = _rmcmd(s, 'code')
    def detex(s): 
    152170    s = _rmcmd(s, 'subsubsection')
    153171    s = _rmcmd(s, 'note', 'NOTE: ', '')
    154172    s = _rmcmd(s, 'emph', '*', '*')
     173    s = _rmcmd(s, 'textbf', '*', '*')
    155174
    156175    s = re.sub(itempattern, itemreplace, s)
    157    
    158     for a,b in substitutes:
     176
     177    if not embedded: # not in the notebook
     178        for a,b in math_substitutes:  # do math substitutions
     179            s = s.replace(a,b)
     180        s = s.replace('\\','')        # nuke backslashes
     181        s = s.replace('.. math::\n', '')  # get rid of .. math:: directives
     182    else:
     183        s = s.replace('\\','\\\\')    # double up backslashes for jsMath
     184    for a,b in nonmath_substitutes:
    159185        s = s.replace(a,b)
    160186    return s
    161187
    162 def format(s):
     188def format(s, embedded=False):
    163189    r"""
    164190    Format Sage documentation ``s`` for viewing with IPython.
    165191
    def format(s): 
    167193    text, and if ``s`` contains a string of the form "<<<obj>>>",
    168194    then it replaces it with the docstring for "obj".
    169195
    170     INPUT: ``s`` - string
     196    INPUT:
     197
     198    - ``s`` - string
     199    - ``embedded`` - boolean (optional, default False)
    171200
    172201    OUTPUT: string
    173202
     203    Set ``embedded`` equal to True if formatting for use in the
     204    notebook; this just gets passed as an argument to ``detex``.
     205
    174206    EXAMPLES::
    175207
    176208        sage: from sage.misc.sagedoc import format
    def format(s): 
    228260        s = s[:i] + '\n' + t + s[i+6+j:]
    229261           
    230262    if 'nodetex' not in directives:
    231         s = detex(s)
     263        s = detex(s, embedded=embedded)
    232264    else:
    233265        # strip the 'nodetex' directive from s
    234266        s = s.replace('nodetex', '', 1)
  • sage/misc/sageinspect.py

    diff --git a/sage/misc/sageinspect.py b/sage/misc/sageinspect.py
    a b Unfortunately, there is no argspec extra 
    113113
    114114import inspect
    115115import os
     116EMBEDDED_MODE = False
    116117
    117118def isclassinstance(obj):
    118119    r"""
    def sage_getdef(obj, obj_name=''): 
    399400        if s[:4] == 'self':
    400401            s = s[4:]
    401402        s = s.lstrip(',').strip()
     403        # for use with typesetting the definition with the notebook:
     404        # sometimes s contains "*args" or "**keywds", and the
     405        # asterisks confuse ReST/sphinx/docutils, so escape them:
     406        # change * to \*, and change ** to \**.
     407        if EMBEDDED_MODE:
     408            s = s.replace('**', '\\**')  # replace ** with \**
     409            t = ''
     410            while True:  # replace * with \*
     411                i = s.find('*')
     412                if i == -1:
     413                    break
     414                elif i > 0 and s[i-1] == '\\':
     415                    if s[i+1] == "*":
     416                        t += s[:i+2]
     417                        s = s[i+2:]
     418                    else:
     419                        t += s[:i+1]
     420                        s = s[i+1:]
     421                    continue
     422                elif i > 0 and s[i-1] == '*':
     423                    t += s[:i+1]
     424                    s = s[i+1:]
     425                    continue
     426                else:
     427                    t += s[:i] + '\\*'
     428                    s = s[i+1:]
     429            s = t + s
    402430        return obj_name + '(' + s + ')'
    403431    except (AttributeError, TypeError, ValueError):
    404432        return '%s( [noargspec] )'%obj_name
    def sage_getdoc(obj, obj_name=''): 
    438466
    439467    if r is None:
    440468        return ''
    441     s = sage.misc.sagedoc.format(str(r))
     469
     470    s = sage.misc.sagedoc.format(str(r), embedded=EMBEDDED_MODE)
    442471
    443472    # If there is a Cython embedded position, it needs to be stripped
    444473    pos = _extract_embedded_position(s)
  • sage/server/notebook/cell.py

    diff --git a/sage/server/notebook/cell.py b/sage/server/notebook/cell.py
    a b re_cell_2 = re.compile("'cell://.*?'")  
    3434
    3535import os, shutil
    3636
    37 from   sage.misc.misc import word_wrap
     37from   sage.misc.misc import word_wrap, SAGE_DOC
    3838from   sage.misc.html import math_parse
    3939from   sage.misc.preparser import strip_string_literals
    4040from   sage.misc.package   import is_package_installed
    if is_package_installed("tinyMCE"): 
    4646else:
    4747    JEDITABLE_TINYMCE = False
    4848
     49# Introspection.  The cache directory is a module-scope variable set
     50# in the first call to Cell.set_introspect_html().
     51import errno, hashlib, time
     52from sphinx.application import Sphinx
     53_SAGE_INTROSPECT = None
    4954
    5055class Cell_generic:
    5156    def is_interactive_cell(self):
    class Cell(Cell_generic): 
    14301435    #################
    14311436    # Introspection #
    14321437    #################
    1433     def set_introspect_html(self, html, completing=False):
    1434         if completing:
     1438    def set_introspect_html(self, html, completing=False, verbose=False):
     1439        """
     1440        If ``verbose`` is True, print verbose output about notebook
     1441        introspection to the command-line.  However, the argument
     1442        ``verbose`` is not easily accessible now -- if you need to
     1443        debug, you have to edit this file, changing its value to True,
     1444        and run 'sage -b'.
     1445        """
     1446        if html == "" or completing:
    14351447            self.__introspect_html = html
     1448        elif html.find("`") == -1 and html.find("::") == -1:
     1449            # html doesn't seem to be in ReST format so use docutils
     1450            # to process the preamble ("**File:**" etc.)  and put
     1451            # everything else in a <pre> block.
     1452            i = html.find("**Docstring:**")
     1453            if i != -1:
     1454                preamble = html[:i+14]
     1455                from docutils.core import publish_parts
     1456                preamble = publish_parts(html[:i+14], writer_name='html')['body']
     1457                html = html[i+14:]
     1458            else:
     1459                preamble = ""
     1460            self.__introspect_html = '<div class="docstring">' + preamble + '<pre>' + html + '</pre></div>'
    14361461        else:
    1437             html = escape(html).strip()
    1438             self.__introspect_html = '<pre class="introspection">'+html+'</pre>'
     1462            # html is in ReST format, so use Sphinx to process it
     1463           
     1464            # Set the location of the introspection cache, "permanent"
     1465            # or temporary.  The former, DOT_SAGE/sage_notebook/doc,
     1466            # can pool queries from multiple worksheet processes.  The
     1467            # latter is exclusive to a worksheet's process.  The Sage
     1468            # cleaner should delete the temporary directory (or
     1469            # directories) after the notebook server exits.
     1470            global _SAGE_INTROSPECT
     1471
     1472            if _SAGE_INTROSPECT is None:
     1473                from sage.misc.misc import DOT_SAGE, tmp_dir
     1474                # It's important to use os.path.join, instead of +,
     1475                # because Sphinx counts on normalized paths.  It's also
     1476                # more portable.
     1477                std_doc_dir = os.path.join(DOT_SAGE, 'sage_notebook/doc')
     1478                try:
     1479                    os.makedirs(std_doc_dir)
     1480                    _SAGE_INTROSPECT = std_doc_dir
     1481                except OSError, error:
     1482                    if error.errno == errno.EEXIST:
     1483                        if os.access(std_doc_dir, os.R_OK | os.W_OK | os.X_OK):
     1484                            _SAGE_INTROSPECT = std_doc_dir
     1485                        else:
     1486                            _SAGE_INTROSPECT = tmp_dir()
     1487                    else:
     1488                        _SAGE_INTROSPECT = tmp_dir()
     1489                if verbose:
     1490                    print 'Introspection cache: ', _SAGE_INTROSPECT
     1491                       
     1492            # We get a quick checksum of the input.  MD5 admits
     1493            # collisions, but we're not concerned about such security
     1494            # issues here.  Of course, if performance permits, we can
     1495            # choose a more robust hash function.
     1496            hash = hashlib.md5(html).hexdigest()
     1497            base_name = os.path.join(_SAGE_INTROSPECT, hash)
     1498            html_name = base_name + '.html'
     1499
     1500            # Multiple processes might try to read/write the target
     1501            # HTML file simultaneously.  We use a file-based lock.
     1502            # Since we care only about the target's contents, and
     1503            # we've configured Sphinx accordingly, we allow multiple
     1504            # simultaneous instances of Sphinx, as long as their
     1505            # targets are different.  Systems which don't properly
     1506            # implement os.O_EXCL may require coarser locking.
     1507
     1508            # The Pythonic cross-platform file lock below is adapted
     1509            # from
     1510            # http://www.evanfosmark.com/2009/01/cross-platform-file-locking-support-in-python/
     1511            lock_name = base_name + '.lock'
     1512
     1513            # Try to acquire the lock, periodically.  If we time out,
     1514            # we fall back to plainly formatted documentation.
     1515            timeout = 0.5
     1516            delay = 0.05
     1517            start_time = time.time()
     1518
     1519            while True:
     1520                try:
     1521                    # This operation is atomic on platforms which
     1522                    # properly implement os.O_EXCL:
     1523                    fd_lock = os.open(lock_name, os.O_CREAT | os.O_EXCL | os.O_RDWR)
     1524                    break;
     1525                except OSError, err:
     1526                    if (err.errno != errno.EEXIST) or (time.time() - start_time >= timeout):
     1527                        plain_html = escape(html).strip()
     1528                        self.__introspect_html = '<pre class="introspection">' + plain_html + '</pre>'
     1529                        return
     1530                    time.sleep(delay)
     1531
     1532            # We've acquired the lock.  Use cached HTML or run Sphinx.
     1533            try:
     1534                open(html_name, 'r')
     1535                if verbose:
     1536                    print 'Found: %s' % html_name
     1537            except IOError:
     1538                html = html.replace('\\\\', '\\')
     1539                rst_name = base_name + '.rst'
     1540                fd_rst = open(rst_name, 'w')
     1541                fd_rst.write(html)
     1542                fd_rst.close()
     1543
     1544                # Sphinx setup.  The constructor is Sphinx(srcdir,
     1545                # confdir, outdir, doctreedir, buildername,
     1546                # confoverrides, status, warning, freshenv).
     1547                srcdir = os.path.normpath(_SAGE_INTROSPECT)
     1548
     1549                # Note: It's crucial that confdir* contains a
     1550                # customized conf.py and layout.html.  In particular,
     1551                # we've disabled index generation and told Sphinx to
     1552                # output almost exactly the HTML we display.  Sphinx
     1553                # also pickles its environment in doctreedir, but we
     1554                # force Sphinx never to load this pickle with
     1555                # freshenv=True.
     1556                confdir = os.path.join(SAGE_DOC, 'en/introspect')
     1557                doctreedir = os.path.normpath(base_name)
     1558                confoverrides = {'html_context' : {}, 'master_doc' : hash}
     1559
     1560                # To suppress output, use this:
     1561
     1562                if verbose:
     1563                    import sys
     1564                    sphinx_app = Sphinx(srcdir, confdir, srcdir, doctreedir, 'html', confoverrides, sys.stdout, sys.stderr, True)
     1565                else:
     1566                    sphinx_app = Sphinx(srcdir, confdir, srcdir, doctreedir, 'html', confoverrides, None, None, True)
     1567
     1568                # Run Sphinx. The first argument corresponds to
     1569                # sphinx-build's "write all files" -a flag, which we
     1570                # set to None.
     1571                sphinx_app.build(None, [rst_name])
     1572
     1573                # We delete .rst files, so future Sphinx runs don't
     1574                # keep track of them.  We also delete doctrees.
     1575                try:
     1576                    os.unlink(rst_name)
     1577                except OSError:
     1578                    pass
     1579                try:
     1580                    shutil.rmtree(doctreedir)
     1581                    os.unlink(doctreedir)
     1582                except OSError:
     1583                    pass
     1584
     1585                if verbose:
     1586                    print 'Built: %s' % html_name
     1587            finally:
     1588                # Contents should be flushed on close().
     1589                fd_html = open(html_name, 'r')
     1590                new_html = fd_html.read()
     1591                fd_html.close()
     1592
     1593                # We release the lock and delete the lock file.
     1594                os.close(fd_lock)
     1595                os.unlink(lock_name)
     1596
     1597                new_html = new_html.replace('<pre>', '<pre class="literal-block">')
     1598                self.__introspect_html = new_html
     1599                return
    14391600
    14401601    def introspect_html(self):
    14411602        if not self.introspect():
  • sage/server/notebook/css.py

    diff --git a/sage/server/notebook/css.py b/sage/server/notebook/css.py
    a b div.slideshow_progress_text{ 
    293293div.introspection {
    294294}
    295295
     296div.docstring {
     297  font-family:arial;
     298  background-color: #fafafa;
     299  color: black;
     300  border: solid 1px black;
     301  padding:8px;
     302  margin:8px;
     303}
     304
     305pre.literal-block {
     306  background-color: #ffffff;
     307  color: black;
     308  padding: 0 0 0 5px;
     309  border-left: 2px solid #c0c0c0;
     310}
     311
    296312pre.introspection {
    297313  font-family: monospace;
    298314  font-size:15px;
    299   background-color: #efefef;
     315  background-color: #f1f1f1;
     316  color: blue;
    300317  border: solid 1px black;
    301318  padding:8px;
    302319  margin:8px;
    span.pingdown { 
    16641681   background-color: #990000;   
    16651682}
    16661683
     1684
     1685
     1686/* These have been scraped directly from pygment. */
     1687
     1688.hll { background-color: #ffffcc }
     1689.c { color: #408090; font-style: italic } /* Comment */
     1690.err { border: 1px solid #FF0000 } /* Error */
     1691.k { color: #007020; font-weight: bold } /* Keyword */
     1692.o { color: #666666 } /* Operator */
     1693.cm { color: #408090; font-style: italic } /* Comment.Multiline */
     1694.cp { color: #007020 } /* Comment.Preproc */
     1695.c1 { color: #408090; font-style: italic } /* Comment.Single */
     1696.cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
     1697.gd { color: #A00000 } /* Generic.Deleted */
     1698.ge { font-style: italic } /* Generic.Emph */
     1699.gr { color: #FF0000 } /* Generic.Error */
     1700.gh { color: #000080; font-weight: bold } /* Generic.Heading */
     1701.gi { color: #00A000 } /* Generic.Inserted */
     1702.go { color: #0000aa } /* Generic.Output */
     1703.gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
     1704.gs { font-weight: bold } /* Generic.Strong */
     1705.gu { color: #800080; font-weight: bold } /* Generic.Subheading */
     1706.gt { color: #0040D0 } /* Generic.Traceback */
     1707.kc { color: #007020; font-weight: bold } /* Keyword.Constant */
     1708.kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
     1709.kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
     1710.kp { color: #007020 } /* Keyword.Pseudo */
     1711.kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
     1712.kt { color: #902000 } /* Keyword.Type */
     1713.m { color: #208050 } /* Literal.Number */
     1714.s { color: #4070a0 } /* Literal.String */
     1715.na { color: #4070a0 } /* Name.Attribute */
     1716.nb { color: #007020 } /* Name.Builtin */
     1717.nc { color: #0e84b5; font-weight: bold } /* Name.Class */
     1718.no { color: #60add5 } /* Name.Constant */
     1719.nd { color: #555555; font-weight: bold } /* Name.Decorator */
     1720.ni { color: #d55537; font-weight: bold } /* Name.Entity */
     1721.ne { color: #007020 } /* Name.Exception */
     1722.nf { color: #06287e } /* Name.Function */
     1723.nl { color: #002070; font-weight: bold } /* Name.Label */
     1724.nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
     1725.nt { color: #062873; font-weight: bold } /* Name.Tag */
     1726.nv { color: #bb60d5 } /* Name.Variable */
     1727.ow { color: #007020; font-weight: bold } /* Operator.Word */
     1728.w { color: #bbbbbb } /* Text.Whitespace */
     1729.mf { color: #208050 } /* Literal.Number.Float */
     1730.mh { color: #208050 } /* Literal.Number.Hex */
     1731.mi { color: #208050 } /* Literal.Number.Integer */
     1732.mo { color: #208050 } /* Literal.Number.Oct */
     1733.sb { color: #4070a0 } /* Literal.String.Backtick */
     1734.sc { color: #4070a0 } /* Literal.String.Char */
     1735.sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
     1736.s2 { color: #4070a0 } /* Literal.String.Double */
     1737.se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
     1738.sh { color: #4070a0 } /* Literal.String.Heredoc */
     1739.si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
     1740.sx { color: #c65d09 } /* Literal.String.Other */
     1741.sr { color: #235388 } /* Literal.String.Regex */
     1742.s1 { color: #4070a0 } /* Literal.String.Single */
     1743.ss { color: #517918 } /* Literal.String.Symbol */
     1744.bp { color: #007020 } /* Name.Builtin.Pseudo */
     1745.vc { color: #bb60d5 } /* Name.Variable.Class */
     1746.vg { color: #bb60d5 } /* Name.Variable.Global */
     1747.vi { color: #bb60d5 } /* Name.Variable.Instance */
     1748.il { color: #208050 } /* Literal.Number.Integer.Long */
     1749
     1750/* end stuff scraped from pygment */
     1751
    16671752"""
    16681753    if color == 'gmail':
    16691754        color1 = '#c3d9ff'
  • sage/server/notebook/templates/notebook_lib.js

    diff --git a/sage/server/notebook/templates/notebook_lib.js b/sage/server/notebook/templates/notebook_lib.js
    a b function update_introspection_text() { 
    892892            halt_introspection();
    893893            return;
    894894        }
     895
    895896        d.innerHTML = introspection_text;
     897
     898        if (contains_jsmath(introspection_text)) {
     899            try {
     900                jsMath.ProcessBeforeShowing(d);
     901            } catch(e) {
     902                text_cell.innerHTML = jsmath_font_msg + d.innerHTML;
     903            }
     904        }
     905
    896906        if(replacing)
    897907            select_replacement_element();
    898908    } else {
    function set_output_text(id, text, wrapp 
    28912901        cell_output.innerHTML = '';
    28922902        cell_output_nowrap.innerHTML = '';
    28932903        cell_output_html.innerHTML = introspect_html;
     2904        if (contains_jsmath(introspect_html)) {
     2905            try {
     2906                jsMath.ProcessBeforeShowing(cell_output_html);
     2907            } catch(e) {
     2908                cell_output.innerHTML = jsmath_font_msg + cell_output_html.innerHTML;
     2909            }
     2910        }
    28942911    }
    28952912}
    28962913
  • sage/server/support.py

    diff --git a/sage/server/support.py b/sage/server/support.py
    a b def init(object_directory=None, globs={} 
    5353        sage.structure.sage_object.base=object_directory
    5454    sage.misc.latex.EMBEDDED_MODE = True
    5555    sage.misc.pager.EMBEDDED_MODE = True
     56    sage.misc.sageinspect.EMBEDDED_MODE = True
    5657
    5758    setup_systems(globs)
    5859    sage.misc.session.init(globs)
    def docstring(obj_name, globs, system='s 
    191192    except (AttributeError, NameError, SyntaxError):
    192193        return "No object '%s' currently defined."%obj_name
    193194    s  = ''
     195    newline = "\n\n"  # blank line to start new paragraph
    194196    try:
    195197        filename = sageinspect.sage_getfile(obj)
    196198        #i = filename.find('site-packages/sage/')
    197199        #if i == -1:
    198         s += 'File:        %s\n'%filename
     200        s += '**File:** %s'%filename
     201        s += newline
    199202        #else:
    200203        #    file = filename[i+len('site-packages/sage/'):]
    201204        #    s += 'File:        <html><a href="src_browser?%s">%s</a></html>\n'%(file,file)
    202205    except TypeError:
    203206        pass
    204     s += 'Type:        %s\n'%type(obj)
    205     s += 'Definition:  %s\n'%sageinspect.sage_getdef(obj, obj_name)
    206     s += 'Docstring: \n%s\n'%sageinspect.sage_getdoc(obj, obj_name)
     207    s += '**Type:** %s'%type(obj)
     208    s += newline
     209    s += '**Definition:** %s'%sageinspect.sage_getdef(obj, obj_name)
     210    s += newline
     211    s += '**Docstring:**'
     212    s += newline
     213    s += sageinspect.sage_getdoc(obj, obj_name)
    207214    return s.rstrip()
    208215
    209216def source_code(s, globs, system='sage'):
    def source_code(s, globs, system='sage') 
    229236            return obj._sage_src_()
    230237        except:
    231238            pass
     239        newline = "\n\n"  # blank line to start new paragraph
     240        indent = "    "   # indent source code to mark it as a code block
     241
    232242        filename = sageinspect.sage_getfile(obj)
    233243        lines, lineno = sageinspect.sage_getsourcelines(obj, is_binary=False)
    234         src = ''.join(lines)
    235         src = sagedoc.format_src(src)
     244        src = indent.join(lines)
     245        src = indent + sagedoc.format_src(src)
    236246        if not lineno is None:
    237             src = "File: %s\nSource Code (starting at line %s):\n%s"%(filename, lineno, src)
    238         return src
     247            output = "**File:** %s"%filename
     248            output += newline
     249            output += "**Source Code** (starting at line %s)::"%lineno
     250            output += newline
     251            output += src
     252        return output
    239253   
    240254    except (TypeError, IndexError), msg:
    241255        print msg