Repository: PyCQA/flake8

Issue:
Display list of available formatters with help for --format
In GitLab by @blueyed on Apr 26, 2018, 03:32

`flake8 --help` contains:

> --format=format       Format errors according to the chosen formatter.

It would be nice/helpful if the list of available formats would be listed there.

Discussion:

Patch:
diff --git a/src/flake8/main/application.py b/src/flake8/main/application.py
index 13ece4e..5178abb 100644
--- a/src/flake8/main/application.py
+++ b/src/flake8/main/application.py
@@ -132,6 +132,7 @@ class Application:
             version=flake8.__version__,
             plugin_versions=self.plugins.versions_str(),
             parents=[self.prelim_arg_parser],
+            formatter_names=list(self.plugins.reporters),
         )
         options.register_default_options(self.option_manager)
         self.option_manager.register_plugins(self.plugins)
diff --git a/src/flake8/main/options.py b/src/flake8/main/options.py
index 9b374ab..86a6cf8 100644
--- a/src/flake8/main/options.py
+++ b/src/flake8/main/options.py
@@ -220,7 +220,15 @@ def register_default_options(option_manager: OptionManager) -> None:
         metavar="format",
         default="default",
         parse_from_config=True,
-        help="Format errors according to the chosen formatter.",
+        help=(
+            f"Format errors according to the chosen formatter "
+            f"({', '.join(sorted(option_manager.formatter_names))}) "
+            f"or a format string containing %%-style "
+            f"mapping keys (code, col, path, row, text). "
+            f"For example, "
+            f"``--format=pylint`` or ``--format='%%(path)s %%(code)s'``. "
+            f"(Default: %(default)s)"
+        ),
     )
 
     add_option(
diff --git a/src/flake8/options/manager.py b/src/flake8/options/manager.py
index e333c9e..7c40cb9 100644
--- a/src/flake8/options/manager.py
+++ b/src/flake8/options/manager.py
@@ -317,6 +317,7 @@ class OptionManager:
         version: str,
         plugin_versions: str,
         parents: list[argparse.ArgumentParser],
+        formatter_names: list[str],
     ) -> None:
         """Initialize an instance of an OptionManager.
 
@@ -330,6 +331,7 @@ class OptionManager:
             A list of ArgumentParser objects whose arguments should also be
             included.
         """
+        self.formatter_names = formatter_names
         self.parser = argparse.ArgumentParser(
             prog="flake8",
             usage="%(prog)s [options] file file ...",


Test patch:
diff --git a/tests/integration/test_aggregator.py b/tests/integration/test_aggregator.py
index a5b39d7..006ac5f 100644
--- a/tests/integration/test_aggregator.py
+++ b/tests/integration/test_aggregator.py
@@ -18,6 +18,7 @@ def optmanager():
         version="3.0.0",
         plugin_versions="",
         parents=[],
+        formatter_names=[],
     )
     options.register_default_options(option_manager)
     return option_manager
diff --git a/tests/integration/test_main.py b/tests/integration/test_main.py
index e711fb3..dfa0e0b 100644
--- a/tests/integration/test_main.py
+++ b/tests/integration/test_main.py
@@ -406,3 +406,13 @@ The specified config file does not exist: missing.cfg
     out, err = capsys.readouterr()
     assert out == expected
     assert err == ""
+
+
+def test_format_option_help(capsys):
+    """Test that help displays list of available formatters."""
+    with pytest.raises(SystemExit):
+        cli.main(["--help"])
+
+    out, err = capsys.readouterr()
+    assert "(default, pylint, quiet-filename, quiet-nothing)" in out
+    assert err == ""
diff --git a/tests/integration/test_plugins.py b/tests/integration/test_plugins.py
index 0b4424a..edba048 100644
--- a/tests/integration/test_plugins.py
+++ b/tests/integration/test_plugins.py
@@ -100,6 +100,7 @@ def test_local_plugin_can_add_option(local_config):
         version="123",
         plugin_versions="",
         parents=[stage1_parser],
+        formatter_names=[],
     )
     register_default_options(option_manager)
     option_manager.register_plugins(loaded_plugins)
diff --git a/tests/unit/test_option_manager.py b/tests/unit/test_option_manager.py
index d5b88c3..3d3ddc1 100644
--- a/tests/unit/test_option_manager.py
+++ b/tests/unit/test_option_manager.py
@@ -17,7 +17,10 @@ TEST_VERSION = "3.0.0b1"
 def optmanager():
     """Generate a simple OptionManager with default test arguments."""
     return manager.OptionManager(
-        version=TEST_VERSION, plugin_versions="", parents=[]
+        version=TEST_VERSION,
+        plugin_versions="",
+        parents=[],
+        formatter_names=[],
     )
 
 
@@ -34,7 +37,10 @@ def test_option_manager_including_parent_options():
 
     # WHEN
     optmanager = manager.OptionManager(
-        version=TEST_VERSION, plugin_versions="", parents=[parent_parser]
+        version=TEST_VERSION,
+        plugin_versions="",
+        parents=[parent_parser],
+        formatter_names=[],
     )
     options = optmanager.parse_args(["--parent", "foo"])
 
diff --git a/tests/unit/test_options_config.py b/tests/unit/test_options_config.py
index 0890ea9..8c8f0cb 100644
--- a/tests/unit/test_options_config.py
+++ b/tests/unit/test_options_config.py
@@ -168,7 +168,9 @@ def test_load_extra_config_utf8(tmpdir):
 
 @pytest.fixture
 def opt_manager():
-    ret = OptionManager(version="123", plugin_versions="", parents=[])
+    ret = OptionManager(
+        version="123", plugin_versions="", parents=[], formatter_names=[]
+    )
     register_default_options(ret)
     return ret