From 85748101fcb16682dfd5641979c6e5f025e5a8a5 Mon Sep 17 00:00:00 2001
From: Ulibos <49131389+Ulibos@users.noreply.github.com>
Date: Thu, 25 Jul 2024 05:15:53 +0300
Subject: [PATCH 1/5] sphinx-build: -M flag documented.
---
sphinx/cmd/build.py | 45 ++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 42 insertions(+), 3 deletions(-)
diff --git a/sphinx/cmd/build.py b/sphinx/cmd/build.py
index 02fd99a8ccc..e8041b7440f 100644
--- a/sphinx/cmd/build.py
+++ b/sphinx/cmd/build.py
@@ -9,10 +9,11 @@
import multiprocessing
import os
import pdb # NoQA: T100
+import re
import sys
import traceback
from os import path
-from typing import TYPE_CHECKING, Any, TextIO
+from typing import TYPE_CHECKING, Any, TextIO, IO
from docutils.utils import SystemMessage
@@ -110,10 +111,41 @@ def jobs_argument(value: str) -> int:
else:
return jobs
+class ParagraphFormatter(argparse.HelpFormatter):
+ """Wraps help text as a default formatter but keeps paragraps separated."""
+ _paragraph_matcher = re.compile(r"\n\n+")
+
+ def _fill_text(self, text: str, width: int, indent: str) -> str:
+ import textwrap
+ result: list[str] = []
+ for p in self._paragraph_matcher.split(text):
+ p = self._whitespace_matcher.sub(' ', p).strip()
+ p = textwrap.fill(p, width,
+ initial_indent=indent,
+ subsequent_indent=indent)
+ result.append(p)
+ return '\n\n'.join(result)
+
+class ArgParser(argparse.ArgumentParser):
+ """Wraps standard ArgumentParser to add sphinx-specefic flags to help."""
+ def print_help(self, file: IO[str] | None = None) -> None:
+ from gettext import gettext as _
+ # we inject -M flag action to positionals before printing help
+ # so that there is no risk of side effects on actual execution
+ for action_group in self._action_groups:
+ if not action_group.title == _('positional arguments'):
+ continue
+ m_flag = argparse.Action(["-M"], "BUILDER", # ugly but works
+ help=__('please refer to usage and main help section'))
+ action_group._group_actions.insert(0, m_flag)
+ break
+ return super().print_help(file)
def get_parser() -> argparse.ArgumentParser:
- parser = argparse.ArgumentParser(
- usage='%(prog)s [OPTIONS] SOURCEDIR OUTPUTDIR [FILENAMES...]',
+ parser = ArgParser(
+ usage=( '%(prog)s -M BUILDER SOURCEDIR OUTPUTDIR [OPTIONS]\n'
+ ' %(prog)s [OPTIONS] SOURCEDIR OUTPUTDIR [FILENAMES...]'),
+ formatter_class=ParagraphFormatter,
epilog=__('For more information, visit .'),
description=__("""
Generate documentation from source files.
@@ -123,6 +155,13 @@ def get_parser() -> argparse.ArgumentParser:
settings. The 'sphinx-quickstart' tool may be used to generate template files,
including 'conf.py'
+PLEASE NOTE that there are 2 signatures for 2 usage scenarios. -M flag is a
+special flag that must always come first if used! If present, it alters the
+way the tool works. It can be thought of as a "one-click" solution. It allows
+to build several formats of docs into the same OUTPUTDIR without mixing them
+up (it creates a dedicated directory for each builder). If more control over
+paths is needed then -b flag is the way to go.
+
sphinx-build can create documentation in different formats. A format is
selected by specifying the builder name on the command line; it defaults to
HTML. Builders can also perform other tasks related to documentation
From 2a3733246b1d5b5d9cc99384991242a7c233e200 Mon Sep 17 00:00:00 2001
From: Ulibos <49131389+Ulibos@users.noreply.github.com>
Date: Thu, 25 Jul 2024 22:30:30 +0300
Subject: [PATCH 2/5] sphinx-make: help color changed, --no-color support.
---
sphinx/cmd/make_mode.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/sphinx/cmd/make_mode.py b/sphinx/cmd/make_mode.py
index 01929469cca..1423a213bf9 100644
--- a/sphinx/cmd/make_mode.py
+++ b/sphinx/cmd/make_mode.py
@@ -17,7 +17,7 @@
import sphinx
from sphinx.cmd.build import build_main
-from sphinx.util.console import blue, bold, color_terminal, nocolor
+from sphinx.util.console import yellow, bold, color_terminal, nocolor
from sphinx.util.osutil import rmtree
if sys.version_info >= (3, 11):
@@ -86,14 +86,14 @@ def build_clean(self) -> int:
return 0
def build_help(self) -> None:
- if not color_terminal():
+ if not color_terminal() or '--no-color' in sys.argv or '-N' in sys.argv:
nocolor()
print(bold("Sphinx v%s" % sphinx.__display_version__))
- print("Please use `make %s' where %s is one of" % ((blue('target'),) * 2))
+ print("Please use `make %s' where %s is one of" % ((yellow('target'),) * 2))
for osname, bname, description in BUILDERS:
if not osname or os.name == osname:
- print(f' {blue(bname.ljust(10))} {description}')
+ print(f' {yellow(bname.ljust(10))} {description}')
def build_latexpdf(self) -> int:
if self.run_generic_build('latex') > 0:
From 01bdcf747865971866c224a3d0f58077518e3d21 Mon Sep 17 00:00:00 2001
From: Ulibos <49131389+Ulibos@users.noreply.github.com>
Date: Thu, 25 Jul 2024 23:16:43 +0300
Subject: [PATCH 3/5] docs: more info about -M flag.
---
doc/man/sphinx-build.rst | 6 +++++-
doc/tutorial/getting-started.rst | 8 ++++++++
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/doc/man/sphinx-build.rst b/doc/man/sphinx-build.rst
index a8a21f8ce93..0d49ea469b5 100644
--- a/doc/man/sphinx-build.rst
+++ b/doc/man/sphinx-build.rst
@@ -4,7 +4,8 @@ sphinx-build
Synopsis
--------
-**sphinx-build** [*options*] <*sourcedir*> <*outputdir*> [*filenames* ...]
+| **sphinx-build** -M <*builder*> <*sourcedir*> <*outputdir*> [*options*]
+| **sphinx-build** [*options*] <*sourcedir*> <*outputdir*> [*filenames* ...]
Description
-----------
@@ -12,6 +13,9 @@ Description
:program:`sphinx-build` generates documentation from the files in
```` and places it in the ````.
+Please note that there are 2 signatures for 2 usage scenarios. ``-M`` flag
+invokes a :ref:`make mode `, otherwise it works in a `build mode`.
+
:program:`sphinx-build` looks for ``/conf.py`` for the configuration
settings. :manpage:`sphinx-quickstart(1)` may be used to generate template
files, including ``conf.py``.
diff --git a/doc/tutorial/getting-started.rst b/doc/tutorial/getting-started.rst
index 678f08db3e7..f8e5188218e 100644
--- a/doc/tutorial/getting-started.rst
+++ b/doc/tutorial/getting-started.rst
@@ -106,6 +106,14 @@ the documentation as HTML for the first time. To do that, run this command:
(.venv) $ sphinx-build -M html docs/source/ docs/build/
+.. note::
+
+ Please note that ``-M`` flag is a `make-mode` flag. ``sphinx-build`` also has
+ a `build-mode` that provides more control over cache directories but has less
+ builders available and has a different signature. It is invoked by using a
+ ``-b`` flag. These flags are mutually exclusive. You can find out more in
+ :doc:`sphinx-build's manual `.
+
And finally, open ``docs/build/html/index.html`` in your browser. You should see
something like this:
From 4c23fe141b9d4d8e467c8a5c501574f3bfa02bfe Mon Sep 17 00:00:00 2001
From: Ulibos <49131389+Ulibos@users.noreply.github.com>
Date: Fri, 26 Jul 2024 03:49:16 +0300
Subject: [PATCH 4/5] Fix linting errors for M-flag PR.
---
doc/man/sphinx-build.rst | 2 +-
doc/tutorial/getting-started.rst | 4 ++--
sphinx/cmd/build.py | 19 +++++++++++++------
sphinx/cmd/make_mode.py | 2 +-
4 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/doc/man/sphinx-build.rst b/doc/man/sphinx-build.rst
index 0d49ea469b5..74a546b9175 100644
--- a/doc/man/sphinx-build.rst
+++ b/doc/man/sphinx-build.rst
@@ -14,7 +14,7 @@ Description
```` and places it in the ````.
Please note that there are 2 signatures for 2 usage scenarios. ``-M`` flag
-invokes a :ref:`make mode `, otherwise it works in a `build mode`.
+invokes a :ref:`make mode `, otherwise it works in a *build mode*.
:program:`sphinx-build` looks for ``/conf.py`` for the configuration
settings. :manpage:`sphinx-quickstart(1)` may be used to generate template
diff --git a/doc/tutorial/getting-started.rst b/doc/tutorial/getting-started.rst
index f8e5188218e..3b0821eea16 100644
--- a/doc/tutorial/getting-started.rst
+++ b/doc/tutorial/getting-started.rst
@@ -108,8 +108,8 @@ the documentation as HTML for the first time. To do that, run this command:
.. note::
- Please note that ``-M`` flag is a `make-mode` flag. ``sphinx-build`` also has
- a `build-mode` that provides more control over cache directories but has less
+ Please note that ``-M`` flag is a *make-mode* flag. ``sphinx-build`` also has
+ a *build-mode* that provides more control over cache directories but has less
builders available and has a different signature. It is invoked by using a
``-b`` flag. These flags are mutually exclusive. You can find out more in
:doc:`sphinx-build's manual `.
diff --git a/sphinx/cmd/build.py b/sphinx/cmd/build.py
index e8041b7440f..74e99b1229a 100644
--- a/sphinx/cmd/build.py
+++ b/sphinx/cmd/build.py
@@ -13,7 +13,7 @@
import sys
import traceback
from os import path
-from typing import TYPE_CHECKING, Any, TextIO, IO
+from typing import IO, TYPE_CHECKING, Any, TextIO
from docutils.utils import SystemMessage
@@ -111,8 +111,10 @@ def jobs_argument(value: str) -> int:
else:
return jobs
+
class ParagraphFormatter(argparse.HelpFormatter):
"""Wraps help text as a default formatter but keeps paragraps separated."""
+
_paragraph_matcher = re.compile(r"\n\n+")
def _fill_text(self, text: str, width: int, indent: str) -> str:
@@ -126,25 +128,30 @@ def _fill_text(self, text: str, width: int, indent: str) -> str:
result.append(p)
return '\n\n'.join(result)
+
class ArgParser(argparse.ArgumentParser):
"""Wraps standard ArgumentParser to add sphinx-specefic flags to help."""
+
def print_help(self, file: IO[str] | None = None) -> None:
from gettext import gettext as _
# we inject -M flag action to positionals before printing help
# so that there is no risk of side effects on actual execution
for action_group in self._action_groups:
- if not action_group.title == _('positional arguments'):
+ if action_group.title != _('positional arguments'):
continue
- m_flag = argparse.Action(["-M"], "BUILDER", # ugly but works
- help=__('please refer to usage and main help section'))
+ m_flag = argparse.Action(
+ ["-M"], "BUILDER", # ugly but works
+ help=__('please refer to usage and main help section')
+ )
action_group._group_actions.insert(0, m_flag)
break
return super().print_help(file)
+
def get_parser() -> argparse.ArgumentParser:
parser = ArgParser(
- usage=( '%(prog)s -M BUILDER SOURCEDIR OUTPUTDIR [OPTIONS]\n'
- ' %(prog)s [OPTIONS] SOURCEDIR OUTPUTDIR [FILENAMES...]'),
+ usage=('%(prog)s -M BUILDER SOURCEDIR OUTPUTDIR [OPTIONS]\n '
+ '%(prog)s [OPTIONS] SOURCEDIR OUTPUTDIR [FILENAMES...]'),
formatter_class=ParagraphFormatter,
epilog=__('For more information, visit .'),
description=__("""
diff --git a/sphinx/cmd/make_mode.py b/sphinx/cmd/make_mode.py
index 1423a213bf9..43cc67371a7 100644
--- a/sphinx/cmd/make_mode.py
+++ b/sphinx/cmd/make_mode.py
@@ -17,7 +17,7 @@
import sphinx
from sphinx.cmd.build import build_main
-from sphinx.util.console import yellow, bold, color_terminal, nocolor
+from sphinx.util.console import bold, color_terminal, nocolor, yellow
from sphinx.util.osutil import rmtree
if sys.version_info >= (3, 11):
From 780b4db4b08091ece121a6e6c7435d19cb18ff12 Mon Sep 17 00:00:00 2001
From: Ulibos <49131389+Ulibos@users.noreply.github.com>
Date: Wed, 7 Aug 2024 03:24:07 +0300
Subject: [PATCH 5/5] refactor: implement suggestions from the PR.
---
doc/man/sphinx-build.rst | 8 +++++---
doc/tutorial/getting-started.rst | 9 ++++-----
sphinx/cmd/build.py | 28 +++++++++++++++++-----------
sphinx/cmd/make_mode.py | 3 ++-
4 files changed, 28 insertions(+), 20 deletions(-)
diff --git a/doc/man/sphinx-build.rst b/doc/man/sphinx-build.rst
index 74a546b9175..5a2ee2bc2e0 100644
--- a/doc/man/sphinx-build.rst
+++ b/doc/man/sphinx-build.rst
@@ -4,8 +4,8 @@ sphinx-build
Synopsis
--------
-| **sphinx-build** -M <*builder*> <*sourcedir*> <*outputdir*> [*options*]
| **sphinx-build** [*options*] <*sourcedir*> <*outputdir*> [*filenames* ...]
+| **sphinx-build** -M <*builder*> <*sourcedir*> <*outputdir*> [*options*]
Description
-----------
@@ -13,8 +13,10 @@ Description
:program:`sphinx-build` generates documentation from the files in
```` and places it in the ````.
-Please note that there are 2 signatures for 2 usage scenarios. ``-M`` flag
-invokes a :ref:`make mode `, otherwise it works in a *build mode*.
+The available modes are the *build-mode* via :option:`sphinx-build -b` and the
+*make-mode* via :option:`sphinx-build -M`. Note that these modes have a
+different signature. The *make-mode* always requires the ``-M`` argument to
+come first and options to come last.
:program:`sphinx-build` looks for ``/conf.py`` for the configuration
settings. :manpage:`sphinx-quickstart(1)` may be used to generate template
diff --git a/doc/tutorial/getting-started.rst b/doc/tutorial/getting-started.rst
index 3b0821eea16..7b2e4518bdd 100644
--- a/doc/tutorial/getting-started.rst
+++ b/doc/tutorial/getting-started.rst
@@ -108,11 +108,10 @@ the documentation as HTML for the first time. To do that, run this command:
.. note::
- Please note that ``-M`` flag is a *make-mode* flag. ``sphinx-build`` also has
- a *build-mode* that provides more control over cache directories but has less
- builders available and has a different signature. It is invoked by using a
- ``-b`` flag. These flags are mutually exclusive. You can find out more in
- :doc:`sphinx-build's manual `.
+ :option:`sphinx-build -M` uses the *make-mode* but :program:`sphinx-build`
+ also supports a *build-mode* via :option:`sphinx-build -b` to provide a finer
+ control over the generated artifacts. See the :ref:`sphinx-build's manual
+ ` for details.
And finally, open ``docs/build/html/index.html`` in your browser. You should see
something like this:
diff --git a/sphinx/cmd/build.py b/sphinx/cmd/build.py
index 74e99b1229a..086e310fe65 100644
--- a/sphinx/cmd/build.py
+++ b/sphinx/cmd/build.py
@@ -132,7 +132,7 @@ def _fill_text(self, text: str, width: int, indent: str) -> str:
class ArgParser(argparse.ArgumentParser):
"""Wraps standard ArgumentParser to add sphinx-specefic flags to help."""
- def print_help(self, file: IO[str] | None = None) -> None:
+ def __inject_help_entry(self) -> argparse._ArgumentGroup:
from gettext import gettext as _
# we inject -M flag action to positionals before printing help
# so that there is no risk of side effects on actual execution
@@ -144,14 +144,22 @@ def print_help(self, file: IO[str] | None = None) -> None:
help=__('please refer to usage and main help section')
)
action_group._group_actions.insert(0, m_flag)
- break
- return super().print_help(file)
+ return action_group
+ err = (
+ "Couldn't find the argument group 'positional arguments' to inject "
+ "-M flag's help info into.")
+ raise TypeError(err)
+
+ def print_help(self, file: IO[str] | None = None) -> None:
+ action_group = self.__inject_help_entry()
+ super().print_help(file)
+ del action_group._group_actions[0]
def get_parser() -> argparse.ArgumentParser:
parser = ArgParser(
- usage=('%(prog)s -M BUILDER SOURCEDIR OUTPUTDIR [OPTIONS]\n '
- '%(prog)s [OPTIONS] SOURCEDIR OUTPUTDIR [FILENAMES...]'),
+ usage=('%(prog)s [OPTIONS] SOURCEDIR OUTPUTDIR [FILENAMES...]\n '
+ '%(prog)s -M BUILDER SOURCEDIR OUTPUTDIR [OPTIONS]'),
formatter_class=ParagraphFormatter,
epilog=__('For more information, visit .'),
description=__("""
@@ -162,12 +170,10 @@ def get_parser() -> argparse.ArgumentParser:
settings. The 'sphinx-quickstart' tool may be used to generate template files,
including 'conf.py'
-PLEASE NOTE that there are 2 signatures for 2 usage scenarios. -M flag is a
-special flag that must always come first if used! If present, it alters the
-way the tool works. It can be thought of as a "one-click" solution. It allows
-to build several formats of docs into the same OUTPUTDIR without mixing them
-up (it creates a dedicated directory for each builder). If more control over
-paths is needed then -b flag is the way to go.
+Use the '-M' option to simultaneously build several formats into the same
+OUTPUTDIR. When specified, this option MUST be the first command-line argument.
+If a finer control over the output is needed, use the '-b/--builder' option
+instead. Note that these modes have a different signature.
sphinx-build can create documentation in different formats. A format is
selected by specifying the builder name on the command line; it defaults to
diff --git a/sphinx/cmd/make_mode.py b/sphinx/cmd/make_mode.py
index 43cc67371a7..0692168d9ed 100644
--- a/sphinx/cmd/make_mode.py
+++ b/sphinx/cmd/make_mode.py
@@ -86,7 +86,8 @@ def build_clean(self) -> int:
return 0
def build_help(self) -> None:
- if not color_terminal() or '--no-color' in sys.argv or '-N' in sys.argv:
+ print(self.opts)
+ if not color_terminal() or '--no-color' in self.opts or '-N' in self.opts:
nocolor()
print(bold("Sphinx v%s" % sphinx.__display_version__))