summaryrefslogtreecommitdiffstats
path: root/sphinx/builders/manpage.py
diff options
context:
space:
mode:
Diffstat (limited to 'sphinx/builders/manpage.py')
-rw-r--r--sphinx/builders/manpage.py127
1 files changed, 127 insertions, 0 deletions
diff --git a/sphinx/builders/manpage.py b/sphinx/builders/manpage.py
new file mode 100644
index 0000000..2d35d20
--- /dev/null
+++ b/sphinx/builders/manpage.py
@@ -0,0 +1,127 @@
+"""Manual pages builder."""
+
+from __future__ import annotations
+
+import warnings
+from os import path
+from typing import TYPE_CHECKING, Any
+
+from docutils.frontend import OptionParser
+from docutils.io import FileOutput
+
+from sphinx import addnodes
+from sphinx.builders import Builder
+from sphinx.locale import __
+from sphinx.util import logging
+from sphinx.util.console import darkgreen # type: ignore[attr-defined]
+from sphinx.util.display import progress_message
+from sphinx.util.nodes import inline_all_toctrees
+from sphinx.util.osutil import ensuredir, make_filename_from_project
+from sphinx.writers.manpage import ManualPageTranslator, ManualPageWriter
+
+if TYPE_CHECKING:
+ from sphinx.application import Sphinx
+ from sphinx.config import Config
+
+logger = logging.getLogger(__name__)
+
+
+class ManualPageBuilder(Builder):
+ """
+ Builds groff output in manual page format.
+ """
+ name = 'man'
+ format = 'man'
+ epilog = __('The manual pages are in %(outdir)s.')
+
+ default_translator_class = ManualPageTranslator
+ supported_image_types: list[str] = []
+
+ def init(self) -> None:
+ if not self.config.man_pages:
+ logger.warning(__('no "man_pages" config value found; no manual pages '
+ 'will be written'))
+
+ def get_outdated_docs(self) -> str | list[str]:
+ return 'all manpages' # for now
+
+ def get_target_uri(self, docname: str, typ: str | None = None) -> str:
+ return ''
+
+ @progress_message(__('writing'))
+ def write(self, *ignored: Any) -> None:
+ docwriter = ManualPageWriter(self)
+ with warnings.catch_warnings():
+ warnings.filterwarnings('ignore', category=DeprecationWarning)
+ # DeprecationWarning: The frontend.OptionParser class will be replaced
+ # by a subclass of argparse.ArgumentParser in Docutils 0.21 or later.
+ docsettings: Any = OptionParser(
+ defaults=self.env.settings,
+ components=(docwriter,),
+ read_config_files=True).get_default_values()
+
+ for info in self.config.man_pages:
+ docname, name, description, authors, section = info
+ if docname not in self.env.all_docs:
+ logger.warning(__('"man_pages" config value references unknown '
+ 'document %s'), docname)
+ continue
+ if isinstance(authors, str):
+ if authors:
+ authors = [authors]
+ else:
+ authors = []
+
+ docsettings.title = name
+ docsettings.subtitle = description
+ docsettings.authors = authors
+ docsettings.section = section
+
+ if self.config.man_make_section_directory:
+ dirname = 'man%s' % section
+ ensuredir(path.join(self.outdir, dirname))
+ targetname = f'{dirname}/{name}.{section}'
+ else:
+ targetname = f'{name}.{section}'
+
+ logger.info(darkgreen(targetname) + ' { ', nonl=True)
+ destination = FileOutput(
+ destination_path=path.join(self.outdir, targetname),
+ encoding='utf-8')
+
+ tree = self.env.get_doctree(docname)
+ docnames: set[str] = set()
+ largetree = inline_all_toctrees(self, docnames, docname, tree,
+ darkgreen, [docname])
+ largetree.settings = docsettings
+ logger.info('} ', nonl=True)
+ self.env.resolve_references(largetree, docname, self)
+ # remove pending_xref nodes
+ for pendingnode in largetree.findall(addnodes.pending_xref):
+ pendingnode.replace_self(pendingnode.children)
+
+ docwriter.write(largetree, destination)
+
+ def finish(self) -> None:
+ pass
+
+
+def default_man_pages(config: Config) -> list[tuple[str, str, str, list[str], int]]:
+ """ Better default man_pages settings. """
+ filename = make_filename_from_project(config.project)
+ return [(config.root_doc, filename, f'{config.project} {config.release}',
+ [config.author], 1)]
+
+
+def setup(app: Sphinx) -> dict[str, Any]:
+ app.add_builder(ManualPageBuilder)
+
+ app.add_config_value('man_pages', default_man_pages, False)
+ app.add_config_value('man_show_urls', False, False)
+ app.add_config_value('man_make_section_directory', False, False)
+
+ return {
+ 'version': 'builtin',
+ 'parallel_read_safe': True,
+ 'parallel_write_safe': True,
+ }