This commit is contained in:
Georg Brandl 2010-10-22 10:06:24 +02:00
commit e6f5d36a0b
14 changed files with 1741 additions and 0 deletions

View File

@ -29,6 +29,8 @@ help:
@echo " epub to make an epub file"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run pdflatex"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview over all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@ -131,3 +133,16 @@ linkcheck:
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) _build/doctest
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) _build/texinfo
@echo
@echo "Build finished. The Texinfo files are in _build/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) _build/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C _build/texinfo info
@echo "makeinfo finished; the Info files are in _build/texinfo."

View File

@ -144,6 +144,27 @@ Note that a direct PDF builder using ReportLab is available in `rst2pdf
.. versionadded:: 1.0
.. module:: sphinx.builders.texinfo
.. class:: TexinfoBuilder
This builder produces Texinfo files that can be processed into Info
files by the :program:`makeinfo` program. You have to specify which
documents are to be included in which Texinfo files via the
:confval:`texinfo_documents` configuration value.
The Info format is the basis of the on-line help system used by GNU
Emacs and the terminal-based program :program:`info`. See
:ref:`texinfo-faq` for more details. The Texinfo format is the
official documentation system used by the GNU project. More
information on Texinfo can be found at
`<http://www.gnu.org/software/texinfo/>`_.
Its name is ``texinfo``.
.. versionadded:: 1.1
.. currentmodule:: sphinx.builders.html
.. class:: SerializingHTMLBuilder

View File

@ -64,6 +64,12 @@ man_pages = [
'template generator', '', 1),
]
texinfo_documents = [
('contents', 'sphinx', 'Sphinx Documentation', 'Georg Brandl',
'Sphinx', 'The Sphinx documentation builder.', 'Documentation tools',
1),
]
# We're not using intersphinx right now, but if we did, this would be part of
# the mapping:
intersphinx_mapping = {'python': ('http://docs.python.org/dev', None)}

View File

@ -1040,6 +1040,79 @@ These options influence manual page output.
.. versionadded:: 1.0
.. _texinfo-options:
Options for Texinfo output
--------------------------
These options influence Texinfo output.
.. confval:: texinfo_documents
This value determines how to group the document tree into Texinfo
source files. It must be a list of tuples ``(startdocname,
targetname, title, author, dir_entry, description, category,
toctree_only)``, where the items are:
* *startdocname*: document name that is the "root" of the Texinfo
file. All documents referenced by it in TOC trees will be
included in the Texinfo file too. (If you want only one Texinfo
file, use your :confval:`master_doc` here.)
* *targetname*: file name (no extension) of the Texinfo file in
the output directory.
* *title*: Texinfo document title. Can be empty to use the title of the
*startdoc*.
* *author*: Author for the Texinfo document. Use ``\and`` to
separate multiple authors, as in: ``'John \and Sarah'``.
* *dir_entry*: The name that will appear in the top-level ``DIR``
menu file.
* *description*: Descriptive text to appear in the top-level
``DIR`` menu file.
* *category*: Specifies the section which this entry will appear in
the top-level ``DIR`` menu file.
* *toctree_only*: Must be ``True`` or ``False``. If ``True``, the
*startdoc* document itself is not included in the output, only
the documents referenced by it via TOC trees. With this option,
you can put extra stuff in the master document that shows up in
the HTML, but not the Texinfo output.
.. versionadded:: 1.1
.. confval:: texinfo_appendices
A list of document names to append as an appendix to all manuals.
.. versionadded:: 1.1
.. confval:: texinfo_elements
A dictionary that contains Texinfo snippets that override those Sphinx usually
puts into the generated ``.texi`` files.
* Keys that you may want to override include:
``'paragraphindent'``
Number of spaces to indent the first line of each paragraph,
default ``2``. Specify ``0`` for no indentation.
``'exampleindent'``
Number of spaces to indent the lines for examples or literal blocks, default ``4``.
Specify ``0`` for no indentation.
``'preamble'``
Text inserted as is near the beginning of the file.
* Keys that are set by other options and therefore should not be overridden are:
``'filename'``
``'title'``
``'direntry'``
.. versionadded:: 1.1
.. rubric:: Footnotes
.. [1] A note on available globbing syntax: you can use the standard shell

View File

@ -148,3 +148,112 @@ some notes:
.. _Calibre: http://calibre-ebook.com/
.. _FBreader: http://www.fbreader.org/
.. _Bookworm: http://bookworm.oreilly.com/
.. _texinfo-faq:
Texinfo info
------------
The Texinfo builder is currently in an experimental stage but has
successfully been used to build the documentation for both Sphinx and
Python. The intended use of this builder is to generate Texinfo that
is then processed into Info files.
There are two main programs for reading Info files, ``info`` and GNU
Emacs. The ``info`` program has less features but is available in
most Unix environments and can be quickly accessed from the terminal.
Emacs provides better font and color display and supports extensive
customization (of course).
.. _texinfo-links:
Displaying Links
~~~~~~~~~~~~~~~~
One noticeable problem you may encounter with the generated Info files
is how references are displayed. If you read the source of an Info
file, a reference to this section would look like::
* note Displaying Links: target-id
In the stand-alone reader, ``info``, references are displayed just as
they appear in the source. Emacs, on the other-hand, will by default
replace ``\*note:`` with ``see`` and hide the ``target-id``. For
example:
:ref:`texinfo-links`
The exact behavior of how Emacs displays references is dependent on
the variable ``Info-hide-note-references``. If set to the value of
``hide``, Emacs will hide both the ``\*note:`` part and the
``target-id``. This is generally the best way to view Sphinx-based
documents since they often make frequent use of links and do not take
this limitation into account. However, changing this variable affects
how all Info documents are displayed and most due take this behavior
into account.
If you want Emacs to display Info files produced by Sphinx using the
value ``hide`` for ``Info-hide-note-references`` and the default value
for all other Info files, try adding the following Emacs Lisp code to
your start-up file, ``~/.emacs.d/init.el``.
::
(defadvice info-insert-file-contents (after
sphinx-info-insert-file-contents
activate)
"Hack to make `Info-hide-note-references' buffer-local and
automatically set to `hide' iff it can be determined that this file
was created from a Texinfo file generated by Docutils or Sphinx."
(set (make-local-variable 'Info-hide-note-references)
(default-value 'Info-hide-note-references))
(save-excursion
(save-restriction
(widen) (goto-char (point-min))
(when (re-search-forward
"^Generated by \\(Sphinx\\|Docutils\\)"
(save-excursion (search-forward "" nil t)) t)
(set (make-local-variable 'Info-hide-note-references)
'hide)))))
Notes
~~~~~
The following notes may be helpful if you want to create Texinfo
files:
- Each section corresponds to a different ``node`` in the Info file.
- Some characters cannot be properly escaped in menu entries and
xrefs. The following characters are replaced by spaces in these
contexts: ``@``, ``{``, ``}``, ``.``, ``,``, and ``:``.
- In the HTML and Tex output, the word ``see`` is automatically
inserted before all xrefs.
- Links to external Info files can be created using the somewhat
official URI scheme ``info``. For example::
info:Texinfo#makeinfo_options
which produces:
info:Texinfo#makeinfo_options
- Inline markup appears as follows in Info:
* strong -- \*strong\*
* emphasis -- _emphasis_
* literal -- \`literal'
It is possible to change this behavior using the Texinfo command
``@definfoenclose``. For example, to make inline markup more
closely resemble reST, add the following to your :file:`conf.py`::
texinfo_elements = {'preamble': """\
@definfoenclose strong,**,**
@definfoenclose emph,*,*
@definfoenclose code,`@w{}`,`@w{}`
"""}

View File

@ -40,6 +40,10 @@ The :program:`sphinx-build` script has several options:
**man**
Build manual pages in groff format for UNIX systems.
**texinfo**
Build Texinfo files that can be processed into Info files using
:program:`makeinfo`.
**text**
Build plain text files.

View File

@ -325,6 +325,7 @@ BUILTIN_BUILDERS = {
'latex': ('latex', 'LaTeXBuilder'),
'text': ('text', 'TextBuilder'),
'man': ('manpage', 'ManualPageBuilder'),
'texinfo': ('texinfo', 'TexinfoBuilder'),
'changes': ('changes', 'ChangesBuilder'),
'linkcheck': ('linkcheck', 'CheckExternalLinksBuilder'),
'websupport': ('websupport', 'WebSupportBuilder'),

229
sphinx/builders/texinfo.py Normal file
View File

@ -0,0 +1,229 @@
# -*- coding: utf-8 -*-
"""
sphinx.builders.texinfo
~~~~~~~~~~~~~~~~~~~~~~~
Texinfo builder.
:copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import os
from os import path
from docutils import nodes
from docutils.io import FileOutput
from docutils.utils import new_document
from docutils.frontend import OptionParser
from sphinx import package_dir, addnodes
from sphinx.locale import _
from sphinx.builders import Builder
from sphinx.environment import NoUri
from sphinx.util.nodes import inline_all_toctrees
from sphinx.util.osutil import SEP, copyfile
from sphinx.util.console import bold, darkgreen
from sphinx.writers.texinfo import TexinfoWriter
TEXINFO_MAKEFILE = '''\
# Makefile for Sphinx Texinfo output
infodir ?= /usr/share/info
MAKEINFO = makeinfo --no-split
MAKEINFO_html = makeinfo --no-split --html
MAKEINFO_plaintext = makeinfo --no-split --plaintext
TEXI2PDF = texi2pdf --batch --expand
INSTALL_INFO = install-info
ALLDOCS = $(basename $(wildcard *.texi))
all: info
info: $(addsuffix .info,$(ALLDOCS))
plaintext: $(addsuffix .txt,$(ALLDOCS))
html: $(addsuffix .html,$(ALLDOCS))
pdf: $(addsuffix .pdf,$(ALLDOCS))
install-info: info
\tfor f in *.info; do \\
\t cp -t $(infodir) "$$f" && \\
\t $(INSTALL_INFO) --info-dir=$(infodir) "$$f" ;\\
\tdone
uninstall-info: info
\tfor f in *.info; do \\
\t rm -f "$(infodir)/$$f" ;\\
\t $(INSTALL_INFO) --delete --info-dir=$(infodir) "$$f" ;\\
\tdone
%.info: %.texi
\t$(MAKEINFO) -o '$@' '$<'
%.txt: %.texi
\t$(MAKEINFO_plaintext) -o '$@' '$<'
%.html: %.texi
\t$(MAKEINFO_html) -o '$@' '$<'
%.pdf: %.texi
\t-$(TEXI2PDF) '$<'
\t-$(TEXI2PDF) '$<'
\t-$(TEXI2PDF) '$<'
clean:
\t-rm -f *.info *.pdf *.txt *.html
\t-rm -f *.log *.ind *.aux *.toc *.syn *.idx *.out *.ilg *.pla *.ky *.pg
\t-rm -f *.vr *.tp *.fn *.fns *.def *.defs *.cp *.cps *.ge *.ges *.mo
.PHONY: all info plaintext html pdf install-info uninstall-info clean
'''
class TexinfoBuilder(Builder):
"""
Builds Texinfo output to create Info.
"""
name = 'texinfo'
format = 'texinfo'
supported_image_types = []
def init(self):
self.docnames = []
self.document_data = []
def get_outdated_docs(self):
return 'all documents' # for now
def get_target_uri(self, docname, typ=None):
if docname not in self.docnames:
raise NoUri
else:
return '%' + docname
def get_relative_uri(self, from_, to, typ=None):
# ignore source path
return self.get_target_uri(to, typ)
def init_document_data(self):
preliminary_document_data = map(list, self.config.texinfo_documents)
if not preliminary_document_data:
self.warn('no "texinfo_documents" config value found; no documents '
'will be written')
return
# assign subdirs to titles
self.titles = []
for entry in preliminary_document_data:
docname = entry[0]
if docname not in self.env.all_docs:
self.warn('"texinfo_documents" config value references unknown '
'document %s' % docname)
continue
self.document_data.append(entry)
if docname.endswith(SEP+'index'):
docname = docname[:-5]
self.titles.append((docname, entry[2]))
def write(self, *ignored):
self.init_document_data()
for entry in self.document_data:
docname, targetname, title, author = entry[:4]
targetname += '.texi'
direntry = description = category = ''
if len(entry) > 6:
direntry, description, category = entry[4:7]
toctree_only = False
if len(entry) > 7:
toctree_only = entry[7]
destination = FileOutput(
destination_path=path.join(self.outdir, targetname),
encoding='utf-8')
self.info("processing " + targetname + "... ", nonl=1)
doctree = self.assemble_doctree(docname, toctree_only,
appendices=(self.config.texinfo_appendices or []))
self.info("writing... ", nonl=1)
# Add an Index section
if self.config.texinfo_domain_indices:
doctree.append(
nodes.section('',
nodes.title(_("Index"),
nodes.Text(_('Index'),
_('Index'))),
nodes.raw('@printindex ge\n',
nodes.Text('@printindex ge\n',
'@printindex ge\n'),
format="texinfo")))
docwriter = TexinfoWriter(self)
settings = OptionParser(
defaults=self.env.settings,
components=(docwriter,)).get_default_values()
settings.author = author
settings.title = title
settings.texinfo_filename = targetname[:-5] + '.info'
settings.texinfo_elements = self.config.texinfo_elements
settings.texinfo_dir_entry = direntry or ''
settings.texinfo_dir_category = category or ''
settings.texinfo_dir_description = description or ''
settings.docname = docname
doctree.settings = settings
docwriter.write(doctree, destination)
self.info("done")
def assemble_doctree(self, indexfile, toctree_only, appendices):
self.docnames = set([indexfile] + appendices)
self.info(darkgreen(indexfile) + " ", nonl=1)
tree = self.env.get_doctree(indexfile)
tree['docname'] = indexfile
if toctree_only:
# extract toctree nodes from the tree and put them in a
# fresh document
new_tree = new_document('<texinfo output>')
new_sect = nodes.section()
new_sect += nodes.title(u'<Set title in conf.py>',
u'<Set title in conf.py>')
new_tree += new_sect
for node in tree.traverse(addnodes.toctree):
new_sect += node
tree = new_tree
largetree = inline_all_toctrees(self, self.docnames, indexfile, tree,
darkgreen)
largetree['docname'] = indexfile
for docname in appendices:
appendix = self.env.get_doctree(docname)
appendix['docname'] = docname
largetree.append(appendix)
self.info()
self.info("resolving references...")
self.env.resolve_references(largetree, indexfile, self)
# TODO: add support for external :ref:s
for pendingnode in largetree.traverse(addnodes.pending_xref):
docname = pendingnode['refdocname']
sectname = pendingnode['refsectname']
newnodes = [nodes.emphasis(sectname, sectname)]
for subdir, title in self.titles:
if docname.startswith(subdir):
newnodes.append(nodes.Text(_(' (in '), _(' (in ')))
newnodes.append(nodes.emphasis(title, title))
newnodes.append(nodes.Text(')', ')'))
break
else:
pass
pendingnode.replace_self(newnodes)
return largetree
def finish(self):
self.info(bold('copying Texinfo support files... '), nonl=True)
# copy Makefile
fn = path.join(self.outdir, 'Makefile')
self.info(fn, nonl=1)
try:
mkfile = open(fn, 'w')
try:
mkfile.write(TEXINFO_MAKEFILE)
finally:
mkfile.close()
except (IOError, OSError), err:
self.warn("error writing file %s: %s" % (fn, err))
self.info(' done')

View File

@ -159,6 +159,12 @@ class Config(object):
# manpage options
man_pages = ([], None),
# Texinfo options
texinfo_documents = ([], None),
texinfo_appendices = ([], None),
texinfo_elements = ({}, None),
texinfo_domain_indices = (True, None),
)
def __init__(self, dirname, filename, overrides, tags):

View File

@ -254,6 +254,19 @@ man_pages = [
('%(master_str)s', '%(project_manpage)s', u'%(project_doc)s',
[u'%(author_str)s'], 1)
]
# -- Options for Texinfo output ------------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('%(master_str)s', '%(project_fn)s', u'%(project_doc)s', u'%(author_str)s',
'%(project_fn)s', 'One line description of project.', 'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
texinfo_appendices = []
'''
EPUB_CONFIG = '''
@ -364,6 +377,8 @@ help:
\t@echo " latexpdf to make LaTeX files and run them through pdflatex"
\t@echo " text to make text files"
\t@echo " man to make manual pages"
\t@echo " texinfo to make Texinfo files"
\t@echo " info to make Texinfo files and run them through makeinfo"
\t@echo " gettext to make PO message catalogs"
\t@echo " changes to make an overview of all changed/added/deprecated items"
\t@echo " linkcheck to check all external links for integrity"
@ -451,6 +466,19 @@ man:
\t@echo
\t@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
\t@echo
\t@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
\t@echo "Run \\`make' in that directory to run these through makeinfo" \\
\t "(use \\`make info' here to do that automatically)."
info:
\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
\t@echo "Running Texinfo files through makeinfo..."
\tmake -C $(BUILDDIR)/texinfo info
\t@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
\t$(SPHINXBUILD) -b gettext $(ALLSPHINXOPTS) $(BUILDDIR)/locale
\t@echo

1186
sphinx/writers/texinfo.py Normal file

File diff suppressed because it is too large Load Diff

View File

@ -49,6 +49,11 @@ latex_documents = [
latex_additional_files = ['svgimg.svg']
texinfo_documents = [
('contents', 'SphinxTests', 'Sphinx Tests',
'Georg Brandl \\and someone else', 'Sphinx Testing', 'Miscellaneous'),
]
value_from_conf_py = 84
coverage_c_path = ['special/*.h']

View File

@ -0,0 +1,54 @@
# -*- coding: utf-8 -*-
"""
test_build_texinfo
~~~~~~~~~~~~~~~~~~
Test the build process with Texinfo builder with the test root.
:copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import os
import sys
from StringIO import StringIO
from subprocess import Popen, PIPE
from sphinx.writers.texinfo import TexinfoTranslator
from util import *
from test_build_html import ENV_WARNINGS
def teardown_module():
(test_root / '_build').rmtree(True)
texinfo_warnfile = StringIO()
if sys.version_info >= (3, 0):
TEXINFO_WARNINGS = remove_unicode_literals(TEXINFO_WARNINGS)
@with_app(buildername='texinfo', warning=texinfo_warnfile, cleanenv=True)
def test_texinfo(app):
app.builder.build_all()
# now, try to run makeinfo over it
cwd = os.getcwd()
os.chdir(app.outdir)
try:
try:
p = Popen(['makeinfo', '--no-split', 'SphinxTests.texi'],
stdout=PIPE, stderr=PIPE)
except OSError:
pass # most likely makeinfo was not found
else:
stdout, stderr = p.communicate()
retcode = p.returncode
if retcode != 0:
print stdout
print stderr
del app.cleanup_trees[:]
assert False, 'makeinfo exited with return code %s' % retcode
finally:
os.chdir(cwd)

View File

@ -171,6 +171,10 @@ def test_quickstart_all_answers(tempdir):
assert ns['man_pages'] == [
('contents', 'stasi', u'STASI™ Documentation',
[u'Wolfgang Schäuble & G\'Beckstein'], 1)]
assert ns['texinfo_documents'] == [
('contents', 'STASI', u'STASI™ Documentation',
u'Wolfgang Schäuble & G\'Beckstein', 'STASI',
'One line description of project.', 'Miscellaneous'),]
assert (tempdir / 'build').isdir()
assert (tempdir / 'source' / '.static').isdir()