mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Implement index entries, production lists and the glossary.
This commit is contained in:
@@ -143,14 +143,14 @@ class Builder(object):
|
||||
"""Load necessary templates and perform initialization."""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_target_uri(self, source_filename):
|
||||
def get_target_uri(self, source_filename, typ=None):
|
||||
"""Return the target URI for a source filename."""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_relative_uri(self, from_, to):
|
||||
def get_relative_uri(self, from_, to, typ=None):
|
||||
"""Return a relative URI between two source filenames."""
|
||||
return relative_uri(self.get_target_uri(from_),
|
||||
self.get_target_uri(to))
|
||||
self.get_target_uri(to, typ))
|
||||
|
||||
def get_outdated_files(self):
|
||||
"""Return a list of output files that are outdated."""
|
||||
@@ -195,10 +195,11 @@ class Builder(object):
|
||||
self.load_env()
|
||||
to_build = list(self.get_outdated_files())
|
||||
if not to_build:
|
||||
self.msg('no files are out of date, exiting.')
|
||||
self.msg('no target files are out of date, exiting.')
|
||||
return
|
||||
self.build(to_build,
|
||||
summary='%d source files that are out of date' % len(to_build))
|
||||
summary='targets for %d source files that are '
|
||||
'out of date' % len(to_build))
|
||||
|
||||
def build(self, filenames, summary=None):
|
||||
if summary:
|
||||
@@ -482,7 +483,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
|
||||
# --------- these are overwritten by the Web builder
|
||||
|
||||
def get_target_uri(self, source_filename):
|
||||
def get_target_uri(self, source_filename, typ=None):
|
||||
return source_filename[:-4] + '.html'
|
||||
|
||||
def get_outdated_files(self):
|
||||
@@ -561,7 +562,7 @@ class WebHTMLBuilder(StandaloneHTMLBuilder):
|
||||
os_path(filename))) > targetmtime:
|
||||
yield filename
|
||||
|
||||
def get_target_uri(self, source_filename):
|
||||
def get_target_uri(self, source_filename, typ=None):
|
||||
if source_filename == 'index.rst':
|
||||
return ''
|
||||
if source_filename.endswith(SEP+'index.rst'):
|
||||
@@ -650,10 +651,14 @@ class LaTeXBuilder(Builder):
|
||||
self.filenames = []
|
||||
|
||||
def get_outdated_files(self):
|
||||
# always rebuild everything for now
|
||||
# XXX always rebuild everything for now
|
||||
return self.env.all_files
|
||||
|
||||
def get_target_uri(self, source_filename):
|
||||
def get_target_uri(self, source_filename, typ=None):
|
||||
if typ == 'token':
|
||||
# token references are always inside production lists and must be
|
||||
# replaced by \token{} in LaTeX
|
||||
return '@token'
|
||||
if source_filename not in self.filenames:
|
||||
raise NoUri
|
||||
else:
|
||||
@@ -661,7 +666,7 @@ class LaTeXBuilder(Builder):
|
||||
|
||||
def get_document_data(self):
|
||||
for toplevel in ["c-api", "distutils", "documenting", "extending",
|
||||
"install", "reference", "tutorial", "using", "library"]:
|
||||
"install", "reference", "tutorial", "using", "library"]:
|
||||
yield (toplevel + SEP + 'index.rst', toplevel+'.tex', 'manual')
|
||||
yield ('whatsnew' + SEP + self.config['version'] + '.rst',
|
||||
'whatsnew.tex', 'howto')
|
||||
@@ -722,6 +727,7 @@ class LaTeXBuilder(Builder):
|
||||
largetree.extend(specials)
|
||||
print
|
||||
print "resolving references..."
|
||||
# XXX problem here: :ref:s to distant PDF
|
||||
self.env.resolve_references(largetree, indexfile, self)
|
||||
return largetree
|
||||
|
||||
|
||||
@@ -37,18 +37,20 @@ def index_directive(name, arguments, options, content, lineno,
|
||||
targetnode = nodes.target('', '', ids=[targetid])
|
||||
state.document.note_explicit_target(targetnode)
|
||||
indexnode = addnodes.index()
|
||||
indexnode['entries'] = arguments
|
||||
indexnode['entries'] = ne = []
|
||||
for entry in arguments:
|
||||
entry = entry.strip()
|
||||
for type in entrytypes:
|
||||
if entry.startswith(type+':'):
|
||||
value = entry[len(type)+1:].strip()
|
||||
env.note_index_entry(type, value, targetid, value)
|
||||
ne.append((type, value, targetid, value))
|
||||
break
|
||||
# shorthand notation for single entries
|
||||
else:
|
||||
for value in entry.split(','):
|
||||
env.note_index_entry('single', value.strip(), targetid, value.strip())
|
||||
ne.append(('single', value.strip(), targetid, value.strip()))
|
||||
return [indexnode, targetnode]
|
||||
|
||||
index_directive.arguments = (1, 0, 1)
|
||||
|
||||
@@ -52,7 +52,7 @@ default_settings = {
|
||||
|
||||
# This is increased every time a new environment attribute is added
|
||||
# to properly invalidate pickle files.
|
||||
ENV_VERSION = 12
|
||||
ENV_VERSION = 13
|
||||
|
||||
|
||||
def walk_depth(node, depth, maxdepth):
|
||||
@@ -620,7 +620,7 @@ class BuildEnvironment:
|
||||
newnode['refid'] = labelid
|
||||
else:
|
||||
newnode['refuri'] = builder.get_relative_uri(
|
||||
docfilename, filename) + '#' + labelid
|
||||
docfilename, filename, typ) + '#' + labelid
|
||||
newnode.append(contnode)
|
||||
elif typ == 'mod':
|
||||
filename, synopsis, platform, deprecated = \
|
||||
|
||||
@@ -97,7 +97,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
'papersize': 'a4paper', # XXX
|
||||
'pointsize': '12pt',
|
||||
'filename': document.settings.filename,
|
||||
'title': None, # comes later
|
||||
'title': None, # is determined later
|
||||
'release': config['release'],
|
||||
'date': time.strftime(config.get('today_fmt', '%B %d, %Y')),
|
||||
}
|
||||
@@ -109,6 +109,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
# flags
|
||||
self.verbatim = None
|
||||
self.in_title = 0
|
||||
self.in_production_list = 0
|
||||
self.first_document = 1
|
||||
self.this_is_the_title = 1
|
||||
self.literal_whitespace = 0
|
||||
@@ -156,10 +157,24 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
raise nodes.SkipNode # XXX
|
||||
|
||||
def visit_glossary(self, node):
|
||||
raise nodes.SkipNode # XXX
|
||||
pass
|
||||
def depart_glossary(self, node):
|
||||
pass
|
||||
|
||||
def visit_productionlist(self, node):
|
||||
raise nodes.SkipNode # XXX
|
||||
self.body.append('\n\n\\begin{productionlist}\n')
|
||||
self.in_production_list = 1
|
||||
def depart_productionlist(self, node):
|
||||
self.body.append('\\end{productionlist}\n\n')
|
||||
self.in_production_list = 0
|
||||
|
||||
def visit_production(self, node):
|
||||
if node['tokenname']:
|
||||
self.body.append('\\production{%s}{' % self.encode(node['tokenname']))
|
||||
else:
|
||||
self.body.append('\\productioncont{')
|
||||
def depart_production(self, node):
|
||||
self.body.append('}\n')
|
||||
|
||||
def visit_transition(self, node):
|
||||
self.body.append('\n\n\\bigskip\\hrule{}\\bigskip\n\n')
|
||||
@@ -410,9 +425,10 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
pass
|
||||
|
||||
def visit_term(self, node):
|
||||
if node.has_key('ids') and node['ids']:
|
||||
self.body.append('\\hypertarget{%s}{}' % node['ids'][0])
|
||||
self.body.append('\\item[')
|
||||
def depart_term(self, node):
|
||||
# definition list term.
|
||||
self.body.append(']\n')
|
||||
|
||||
def visit_classifier(self, node):
|
||||
@@ -461,27 +477,60 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
self.body.append(self.context.pop())
|
||||
|
||||
def visit_target(self, node):
|
||||
# XXX: no "index-" targets
|
||||
def add_target(id):
|
||||
# indexing uses standard LaTeX index markup, so the targets
|
||||
# will be generated differently
|
||||
if not id.startswith('index-'):
|
||||
self.body.append(r'\hypertarget{%s}{' % id)
|
||||
return '}'
|
||||
return ''
|
||||
|
||||
# XXX specialcase 'module-' targets: add \declaremodule
|
||||
# XXX where to put \makemodindex
|
||||
|
||||
if not (node.has_key('refuri') or node.has_key('refid')
|
||||
or node.has_key('refname')):
|
||||
ctx = ''
|
||||
for id in node['ids']:
|
||||
if id not in self.written_ids:
|
||||
self.body.append(r'\hypertarget{%s}{' % id)
|
||||
self.written_ids.add(id)
|
||||
ctx += '}'
|
||||
ctx += add_target(id)
|
||||
self.context.append(ctx)
|
||||
elif node.has_key('refid') and node['refid'] not in self.written_ids:
|
||||
self.body.append(r'\hypertarget{%s}{' % node['refid'])
|
||||
self.context.append(add_target(node['refid']))
|
||||
self.written_ids.add(node['refid'])
|
||||
self.context.append('}')
|
||||
else:
|
||||
self.context.append('')
|
||||
def depart_target(self, node):
|
||||
self.body.append(self.context.pop())
|
||||
|
||||
def visit_index(self, node):
|
||||
raise nodes.SkipNode # XXX
|
||||
indextype_map = {
|
||||
'module': 'refmodindex', # XXX: key?
|
||||
'keyword': 'kwindex',
|
||||
'operator': 'opindex',
|
||||
'object': 'obindex',
|
||||
'exception': 'exindex',
|
||||
'statement': 'stindex',
|
||||
'builtin': 'bifuncindex',
|
||||
}
|
||||
|
||||
def visit_index(self, node, scre=re.compile(r';\s*')):
|
||||
entries = node['entries']
|
||||
for type, string, tid, _ in entries:
|
||||
if type == 'single':
|
||||
self.body.append(r'\index{%s}' % scre.sub('!', self.encode(string)))
|
||||
elif type == 'pair':
|
||||
parts = tuple(self.encode(x.strip()) for x in string.split(';', 1))
|
||||
self.body.append(r'\indexii{%s}{%s}' % parts)
|
||||
elif type == 'triple':
|
||||
parts = tuple(self.encode(x.strip()) for x in string.split(';', 2))
|
||||
self.body.append(r'\indexiii{%s}{%s}{%s}' % parts)
|
||||
elif type in self.indextype_map:
|
||||
self.body.append(r'\%s{%s}' % (self.indextype_map[type],
|
||||
self.encode(string)))
|
||||
else:
|
||||
raise RuntimeError('XXX unknown index entry type')
|
||||
raise nodes.SkipNode
|
||||
|
||||
def visit_reference(self, node):
|
||||
uri = node.get('refuri', '')
|
||||
@@ -493,6 +542,12 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
elif uri.startswith('#'):
|
||||
self.body.append('\\hyperlink{%s}{' % uri[1:])
|
||||
self.context.append('}')
|
||||
elif uri.startswith('@token'):
|
||||
if self.in_production_list:
|
||||
self.body.append('\\token{')
|
||||
else:
|
||||
self.body.append('\\grammartoken{')
|
||||
self.context.append('}')
|
||||
else:
|
||||
raise RuntimeError('XXX malformed reference target %s' % uri)
|
||||
def depart_reference(self, node):
|
||||
|
||||
@@ -855,26 +855,26 @@
|
||||
|
||||
% Use this def/redef approach for \url{} since hyperref defined this already,
|
||||
% but only if we actually used hyperref:
|
||||
\ifpdf
|
||||
\newcommand{\url}[1]{{%
|
||||
\py@pdfstartlink%
|
||||
attr{ /Border [0 0 0] }%
|
||||
user{%
|
||||
/Subtype/Link%
|
||||
/A<<%
|
||||
/Type/Action%
|
||||
/S/URI%
|
||||
/URI(#1)%
|
||||
>>%
|
||||
}%
|
||||
\py@LinkColor% color of the link text
|
||||
\py@smallsize\sf #1%
|
||||
\py@NormalColor% Turn it back off; these are declarative
|
||||
\pdfendlink}% and don't appear bound to the current
|
||||
}% formatting "box".
|
||||
\else
|
||||
\newcommand{\url}[1]{\mbox{\py@smallsize\textsf{#1}}}
|
||||
\fi
|
||||
%\ifpdf
|
||||
% \newcommand{\url}[1]{{%
|
||||
% \py@pdfstartlink%
|
||||
% attr{ /Border [0 0 0] }%
|
||||
% user{%
|
||||
% /Subtype/Link%
|
||||
% /A<<%
|
||||
% /Type/Action%
|
||||
% /S/URI%
|
||||
% /URI(#1)%
|
||||
% >>%
|
||||
% }%
|
||||
% \py@LinkColor% color of the link text
|
||||
% \py@smallsize\sf #1%
|
||||
% \py@NormalColor% Turn it back off; these are declarative
|
||||
% \pdfendlink}% and don't appear bound to the current
|
||||
% }% formatting "box".
|
||||
%\else
|
||||
% \newcommand{\url}[1]{\mbox{\py@smallsize\textsf{#1}}}
|
||||
%\fi
|
||||
\newcommand{\email}[1]{{\py@smallsize\textsf{#1}}}
|
||||
\newcommand{\newsgroup}[1]{{\py@smallsize\textsf{#1}}}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user