buildframework/helium/external/python/lib/common/Sphinx-0.5.1-py2.5.egg/sphinx/directives/other.py
changeset 179 d8ac696cc51f
equal deleted inserted replaced
1:be27ed110b50 179:d8ac696cc51f
       
     1 # -*- coding: utf-8 -*-
       
     2 """
       
     3     sphinx.directives.other
       
     4     ~~~~~~~~~~~~~~~~~~~~~~~
       
     5 
       
     6     :copyright: 2007-2008 by Georg Brandl.
       
     7     :license: BSD.
       
     8 """
       
     9 
       
    10 import re
       
    11 import posixpath
       
    12 
       
    13 from docutils import nodes
       
    14 from docutils.parsers.rst import directives
       
    15 
       
    16 from sphinx import addnodes
       
    17 from sphinx.locale import pairindextypes
       
    18 from sphinx.util import patfilter, ws_re, caption_ref_re
       
    19 from sphinx.util.compat import make_admonition
       
    20 
       
    21 
       
    22 # ------ the TOC tree ---------------------------------------------------------------
       
    23 
       
    24 def toctree_directive(name, arguments, options, content, lineno,
       
    25                       content_offset, block_text, state, state_machine):
       
    26     env = state.document.settings.env
       
    27     suffix = env.config.source_suffix
       
    28     dirname = posixpath.dirname(env.docname)
       
    29     glob = 'glob' in options
       
    30 
       
    31     ret = []
       
    32     subnode = addnodes.toctree()
       
    33     includefiles = []
       
    34     includetitles = {}
       
    35     all_docnames = env.found_docs.copy()
       
    36     # don't add the currently visited file in catch-all patterns
       
    37     all_docnames.remove(env.docname)
       
    38     for entry in content:
       
    39         if not entry:
       
    40             continue
       
    41         if not glob:
       
    42             # look for explicit titles and documents ("Some Title <document>").
       
    43             m = caption_ref_re.match(entry)
       
    44             if m:
       
    45                 docname = m.group(2)
       
    46                 includetitles[docname] = m.group(1)
       
    47             else:
       
    48                 docname = entry
       
    49             # remove suffixes (backwards compatibility)
       
    50             if docname.endswith(suffix):
       
    51                 docname = docname[:-len(suffix)]
       
    52             # absolutize filenames
       
    53             docname = posixpath.normpath(posixpath.join(dirname, docname))
       
    54             if docname not in env.found_docs:
       
    55                 ret.append(state.document.reporter.warning(
       
    56                     'toctree references unknown document %r' % docname, line=lineno))
       
    57             else:
       
    58                 includefiles.append(docname)
       
    59         else:
       
    60             patname = posixpath.normpath(posixpath.join(dirname, entry))
       
    61             docnames = sorted(patfilter(all_docnames, patname))
       
    62             for docname in docnames:
       
    63                 all_docnames.remove(docname) # don't include it again
       
    64                 includefiles.append(docname)
       
    65             if not docnames:
       
    66                 ret.append(state.document.reporter.warning(
       
    67                     'toctree glob pattern %r didn\'t match any documents' % entry,
       
    68                     line=lineno))
       
    69     subnode['includefiles'] = includefiles
       
    70     subnode['includetitles'] = includetitles
       
    71     subnode['maxdepth'] = options.get('maxdepth', -1)
       
    72     subnode['glob'] = glob
       
    73     ret.append(subnode)
       
    74     return ret
       
    75 
       
    76 toctree_directive.content = 1
       
    77 toctree_directive.options = {'maxdepth': int, 'glob': directives.flag}
       
    78 directives.register_directive('toctree', toctree_directive)
       
    79 
       
    80 
       
    81 # ------ section metadata ----------------------------------------------------------
       
    82 
       
    83 def module_directive(name, arguments, options, content, lineno,
       
    84                      content_offset, block_text, state, state_machine):
       
    85     env = state.document.settings.env
       
    86     modname = arguments[0].strip()
       
    87     noindex = 'noindex' in options
       
    88     env.currmodule = modname
       
    89     env.note_module(modname, options.get('synopsis', ''),
       
    90                     options.get('platform', ''),
       
    91                     'deprecated' in options)
       
    92     modulenode = addnodes.module()
       
    93     modulenode['modname'] = modname
       
    94     modulenode['synopsis'] = options.get('synopsis', '')
       
    95     targetnode = nodes.target('', '', ids=['module-' + modname])
       
    96     state.document.note_explicit_target(targetnode)
       
    97     ret = [modulenode, targetnode]
       
    98     if 'platform' in options:
       
    99         modulenode['platform'] = options['platform']
       
   100         node = nodes.paragraph()
       
   101         node += nodes.emphasis('', _('Platforms: '))
       
   102         node += nodes.Text(options['platform'], options['platform'])
       
   103         ret.append(node)
       
   104     # the synopsis isn't printed; in fact, it is only used in the modindex currently
       
   105     if not noindex:
       
   106         indextext = _('%s (module)') % modname
       
   107         inode = addnodes.index(entries=[('single', indextext,
       
   108                                          'module-' + modname, modname)])
       
   109         ret.insert(0, inode)
       
   110     return ret
       
   111 
       
   112 module_directive.arguments = (1, 0, 0)
       
   113 module_directive.options = {'platform': lambda x: x,
       
   114                             'synopsis': lambda x: x,
       
   115                             'noindex': directives.flag,
       
   116                             'deprecated': directives.flag}
       
   117 directives.register_directive('module', module_directive)
       
   118 
       
   119 
       
   120 def currentmodule_directive(name, arguments, options, content, lineno,
       
   121                             content_offset, block_text, state, state_machine):
       
   122     # This directive is just to tell people that we're documenting
       
   123     # stuff in module foo, but links to module foo won't lead here.
       
   124     env = state.document.settings.env
       
   125     modname = arguments[0].strip()
       
   126     if modname == 'None':
       
   127         env.currmodule = None
       
   128     else:
       
   129         env.currmodule = modname
       
   130     return []
       
   131 
       
   132 currentmodule_directive.arguments = (1, 0, 0)
       
   133 directives.register_directive('currentmodule', currentmodule_directive)
       
   134 
       
   135 
       
   136 def author_directive(name, arguments, options, content, lineno,
       
   137                      content_offset, block_text, state, state_machine):
       
   138     # Show authors only if the show_authors option is on
       
   139     env = state.document.settings.env
       
   140     if not env.config.show_authors:
       
   141         return []
       
   142     para = nodes.paragraph()
       
   143     emph = nodes.emphasis()
       
   144     para += emph
       
   145     if name == 'sectionauthor':
       
   146         text = _('Section author: ')
       
   147     elif name == 'moduleauthor':
       
   148         text = _('Module author: ')
       
   149     else:
       
   150         text = _('Author: ')
       
   151     emph += nodes.Text(text, text)
       
   152     inodes, messages = state.inline_text(arguments[0], lineno)
       
   153     emph.extend(inodes)
       
   154     return [para] + messages
       
   155 
       
   156 author_directive.arguments = (1, 0, 1)
       
   157 directives.register_directive('sectionauthor', author_directive)
       
   158 directives.register_directive('moduleauthor', author_directive)
       
   159 
       
   160 
       
   161 def program_directive(name, arguments, options, content, lineno,
       
   162                       content_offset, block_text, state, state_machine):
       
   163     env = state.document.settings.env
       
   164     program = ws_re.sub('-', arguments[0].strip())
       
   165     if program == 'None':
       
   166         env.currprogram = None
       
   167     else:
       
   168         env.currprogram = program
       
   169     return []
       
   170 
       
   171 program_directive.arguments = (1, 0, 1)
       
   172 directives.register_directive('program', program_directive)
       
   173 
       
   174 
       
   175 # ------ index markup --------------------------------------------------------------
       
   176 
       
   177 indextypes = [
       
   178     'single', 'pair', 'triple',
       
   179 ]
       
   180 
       
   181 def index_directive(name, arguments, options, content, lineno,
       
   182                     content_offset, block_text, state, state_machine):
       
   183     arguments = arguments[0].split('\n')
       
   184     env = state.document.settings.env
       
   185     targetid = 'index-%s' % env.index_num
       
   186     env.index_num += 1
       
   187     targetnode = nodes.target('', '', ids=[targetid])
       
   188     state.document.note_explicit_target(targetnode)
       
   189     indexnode = addnodes.index()
       
   190     indexnode['entries'] = ne = []
       
   191     for entry in arguments:
       
   192         entry = entry.strip()
       
   193         for type in pairindextypes:
       
   194             if entry.startswith(type+':'):
       
   195                 value = entry[len(type)+1:].strip()
       
   196                 value = pairindextypes[type] + '; ' + value
       
   197                 ne.append(('pair', value, targetid, value))
       
   198                 break
       
   199         else:
       
   200             for type in indextypes:
       
   201                 if entry.startswith(type+':'):
       
   202                     value = entry[len(type)+1:].strip()
       
   203                     ne.append((type, value, targetid, value))
       
   204                     break
       
   205             # shorthand notation for single entries
       
   206             else:
       
   207                 for value in entry.split(','):
       
   208                     value = value.strip()
       
   209                     if not value:
       
   210                         continue
       
   211                     ne.append(('single', value, targetid, value))
       
   212     return [indexnode, targetnode]
       
   213 
       
   214 index_directive.arguments = (1, 0, 1)
       
   215 directives.register_directive('index', index_directive)
       
   216 
       
   217 # ------ versionadded/versionchanged -----------------------------------------------
       
   218 
       
   219 def version_directive(name, arguments, options, content, lineno,
       
   220                       content_offset, block_text, state, state_machine):
       
   221     node = addnodes.versionmodified()
       
   222     node['type'] = name
       
   223     node['version'] = arguments[0]
       
   224     if len(arguments) == 2:
       
   225         inodes, messages = state.inline_text(arguments[1], lineno+1)
       
   226         node.extend(inodes)
       
   227         if content:
       
   228             state.nested_parse(content, content_offset, node)
       
   229         ret = [node] + messages
       
   230     else:
       
   231         ret = [node]
       
   232     env = state.document.settings.env
       
   233     env.note_versionchange(node['type'], node['version'], node, lineno)
       
   234     return ret
       
   235 
       
   236 version_directive.arguments = (1, 1, 1)
       
   237 version_directive.content = 1
       
   238 
       
   239 directives.register_directive('deprecated', version_directive)
       
   240 directives.register_directive('versionadded', version_directive)
       
   241 directives.register_directive('versionchanged', version_directive)
       
   242 
       
   243 
       
   244 # ------ see also ------------------------------------------------------------------
       
   245 
       
   246 def seealso_directive(name, arguments, options, content, lineno,
       
   247                       content_offset, block_text, state, state_machine):
       
   248     ret = make_admonition(
       
   249         addnodes.seealso, name, [_('See also')], options, content,
       
   250         lineno, content_offset, block_text, state, state_machine)
       
   251     if arguments:
       
   252         argnodes, msgs = state.inline_text(arguments[0], lineno)
       
   253         para = nodes.paragraph()
       
   254         para += argnodes
       
   255         para += msgs
       
   256         ret[0].insert(1, para)
       
   257     return ret
       
   258 
       
   259 seealso_directive.content = 1
       
   260 seealso_directive.arguments = (0, 1, 1)
       
   261 directives.register_directive('seealso', seealso_directive)
       
   262 
       
   263 
       
   264 # ------ production list (for the reference) ---------------------------------------
       
   265 
       
   266 token_re = re.compile('`([a-z_]+)`')
       
   267 
       
   268 def token_xrefs(text, env):
       
   269     retnodes = []
       
   270     pos = 0
       
   271     for m in token_re.finditer(text):
       
   272         if m.start() > pos:
       
   273             txt = text[pos:m.start()]
       
   274             retnodes.append(nodes.Text(txt, txt))
       
   275         refnode = addnodes.pending_xref(m.group(1))
       
   276         refnode['reftype'] = 'token'
       
   277         refnode['reftarget'] = m.group(1)
       
   278         refnode['modname'] = env.currmodule
       
   279         refnode['classname'] = env.currclass
       
   280         refnode += nodes.literal(m.group(1), m.group(1), classes=['xref'])
       
   281         retnodes.append(refnode)
       
   282         pos = m.end()
       
   283     if pos < len(text):
       
   284         retnodes.append(nodes.Text(text[pos:], text[pos:]))
       
   285     return retnodes
       
   286 
       
   287 def productionlist_directive(name, arguments, options, content, lineno,
       
   288                              content_offset, block_text, state, state_machine):
       
   289     env = state.document.settings.env
       
   290     node = addnodes.productionlist()
       
   291     messages = []
       
   292     i = 0
       
   293 
       
   294     for rule in arguments[0].split('\n'):
       
   295         if i == 0 and ':' not in rule:
       
   296             # production group
       
   297             continue
       
   298         i += 1
       
   299         try:
       
   300             name, tokens = rule.split(':', 1)
       
   301         except ValueError:
       
   302             break
       
   303         subnode = addnodes.production()
       
   304         subnode['tokenname'] = name.strip()
       
   305         if subnode['tokenname']:
       
   306             idname = 'grammar-token-%s' % subnode['tokenname']
       
   307             if idname not in state.document.ids:
       
   308                 subnode['ids'].append(idname)
       
   309             state.document.note_implicit_target(subnode, subnode)
       
   310             env.note_reftarget('token', subnode['tokenname'], idname)
       
   311         subnode.extend(token_xrefs(tokens, env))
       
   312         node.append(subnode)
       
   313     return [node] + messages
       
   314 
       
   315 productionlist_directive.content = 0
       
   316 productionlist_directive.arguments = (1, 0, 1)
       
   317 directives.register_directive('productionlist', productionlist_directive)
       
   318 
       
   319 
       
   320 # ------ glossary directive ---------------------------------------------------------
       
   321 
       
   322 def glossary_directive(name, arguments, options, content, lineno,
       
   323                        content_offset, block_text, state, state_machine):
       
   324     """Glossary with cross-reference targets for :term: roles."""
       
   325     env = state.document.settings.env
       
   326     node = addnodes.glossary()
       
   327     state.nested_parse(content, content_offset, node)
       
   328 
       
   329     # the content should be definition lists
       
   330     dls = [child for child in node if isinstance(child, nodes.definition_list)]
       
   331     # now, extract definition terms to enable cross-reference creation
       
   332     for dl in dls:
       
   333         dl['classes'].append('glossary')
       
   334         for li in dl.children:
       
   335             if not li.children or not isinstance(li[0], nodes.term):
       
   336                 continue
       
   337             termtext = li.children[0].astext()
       
   338             new_id = 'term-' + nodes.make_id(termtext)
       
   339             if new_id in env.gloss_entries:
       
   340                 new_id = 'term-' + str(len(env.gloss_entries))
       
   341             env.gloss_entries.add(new_id)
       
   342             li[0]['names'].append(new_id)
       
   343             li[0]['ids'].append(new_id)
       
   344             state.document.settings.env.note_reftarget('term', termtext.lower(),
       
   345                                                        new_id)
       
   346             # add an index entry too
       
   347             indexnode = addnodes.index()
       
   348             indexnode['entries'] = [('single', termtext, new_id, termtext)]
       
   349             li.insert(0, indexnode)
       
   350     return [node]
       
   351 
       
   352 glossary_directive.content = 1
       
   353 glossary_directive.arguments = (0, 0, 0)
       
   354 directives.register_directive('glossary', glossary_directive)
       
   355 
       
   356 
       
   357 # ------ miscellaneous markup -------------------------------------------------------
       
   358 
       
   359 def centered_directive(name, arguments, options, content, lineno,
       
   360                        content_offset, block_text, state, state_machine):
       
   361     if not arguments:
       
   362         return []
       
   363     subnode = addnodes.centered()
       
   364     inodes, messages = state.inline_text(arguments[0], lineno)
       
   365     subnode.extend(inodes)
       
   366     return [subnode] + messages
       
   367 
       
   368 centered_directive.arguments = (1, 0, 1)
       
   369 directives.register_directive('centered', centered_directive)
       
   370 
       
   371 
       
   372 def acks_directive(name, arguments, options, content, lineno,
       
   373                    content_offset, block_text, state, state_machine):
       
   374     node = addnodes.acks()
       
   375     state.nested_parse(content, content_offset, node)
       
   376     if len(node.children) != 1 or not isinstance(node.children[0], nodes.bullet_list):
       
   377         return [state.document.reporter.warning('.. acks content is not a list',
       
   378                                                 line=lineno)]
       
   379     return [node]
       
   380 
       
   381 acks_directive.content = 1
       
   382 acks_directive.arguments = (0, 0, 0)
       
   383 directives.register_directive('acks', acks_directive)
       
   384 
       
   385 
       
   386 def tabularcolumns_directive(name, arguments, options, content, lineno,
       
   387                              content_offset, block_text, state, state_machine):
       
   388     # support giving explicit tabulary column definition to latex
       
   389     node = addnodes.tabular_col_spec()
       
   390     node['spec'] = arguments[0]
       
   391     return [node]
       
   392 
       
   393 tabularcolumns_directive.content = 0
       
   394 tabularcolumns_directive.arguments = (1, 0, 1)
       
   395 directives.register_directive('tabularcolumns', tabularcolumns_directive)
       
   396 
       
   397 
       
   398 # register the standard rst class directive under a different name
       
   399 
       
   400 try:
       
   401     # docutils 0.4
       
   402     from docutils.parsers.rst.directives.misc import class_directive
       
   403     directives.register_directive('cssclass', class_directive)
       
   404 except ImportError:
       
   405     try:
       
   406         # docutils 0.5
       
   407         from docutils.parsers.rst.directives.misc import Class
       
   408         directives.register_directive('cssclass', Class)
       
   409     except ImportError:
       
   410         # whatever :)
       
   411         pass