Repository: pallets/click (python)

Issue:
Flag option with secondary opts: show_default=True does not show value from default_map in "help" output
I'm setting the `default_map` from a config file, and it seems the values from the `default_map` are not correctly shown in the `--help` output if I set `show_default=True` on my option.

My Option looks like this:

```python
@click.option(
    "--long/--short",
    "-l/-s",
    is_flag=True,
    show_default=True,
    help="show additional information like size and creation date",
)
```

I initialize the `default_map` with a custom command class that I attach via the `@click.command` decorator like this `@click.command(cls=ConfigAwareCommand)`

```python
from click import Command as _Command


class ConfigAwareCommand(_Command):
    def __init__(self, *args, **kwargs):
        kwargs["context_settings"] = {
            "default_map": CONFIG.get_cli_command_defaults(kwargs["name"])
        }
        super().__init__(*args, **kwargs)

```

The `default_map` value is in my example `{'long': True}`. In the `--help` output, the default value is shown like this

```
  -l, --long / -s, --short        show additional information like size and
                                  creation date  [default: short]
```

When executing the command, the default value from the `default_map` is used correctly (`long` defaults to `True`).

During debugging, I might have found the culprit inside [src/click/core.py](https://github.com/pallets/click/blob/main/src/click/core.py#L2746)

```python
            elif self.is_bool_flag and self.secondary_opts:
                # For boolean flags that have distinct True/False opts,
                # use the opt without prefix instead of the value.
                default_string = _split_opt(
                    (self.opts if self.default else self.secondary_opts)[0]
                )[1]
```

As you can see, `self.default` is used instead of the `default_value` variable that is initialized [further above](https://github.com/pallets/click/blob/main/src/click/core.py#L2720) this code snippet.

If I change the part of the code above and use `default_value` instead of `self.default` the help output shows the correct default values from the `default_map`.

```python
            elif self.is_bool_flag and self.secondary_opts:
                # For boolean flags that have distinct True/False opts,
                # use the opt without prefix instead of the value.
                default_string = _split_opt(
                    (self.opts if default_value else self.secondary_opts)[0]
                )[1]
```

I am not sure if I do something wrong or if this is indeed a bug.

Environment:

- Python version: 3.10.12
- Click version: 8.1.7


Pull request:
fix bug in show defaults when using a flag option and a default map
In latest main, when a flag option is used with `show_default=True` and a `default_map` is passed, `--help` shows the default value in the decorator and not the value in the default map.

This PR does two things:

- Adds unit tests to demonstrate the bug
- Removes the bug from core

fixes #2632


Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index 8a09daf..7ca76f9 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -12,6 +12,8 @@ Unreleased
     the help for an option. :issue:`2500`
 -   The test runner handles stripping color consistently on Windows.
     :issue:`2705`
+-   Show correct value for flag default when using ``default_map``.
+    :issue:`2632`
 
 
 Version 8.1.7
diff --git a/src/click/core.py b/src/click/core.py
index 367beb2..ab7d452 100644
--- a/src/click/core.py
+++ b/src/click/core.py
@@ -2800,7 +2800,7 @@ class Option(Parameter):
                 # For boolean flags that have distinct True/False opts,
                 # use the opt without prefix instead of the value.
                 default_string = split_opt(
-                    (self.opts if self.default else self.secondary_opts)[0]
+                    (self.opts if default_value else self.secondary_opts)[0]
                 )[1]
             elif self.is_bool_flag and not self.secondary_opts and not default_value:
                 default_string = ""


Test patch:
diff --git a/tests/test_defaults.py b/tests/test_defaults.py
index 5ab05ed..5c5e168 100644
--- a/tests/test_defaults.py
+++ b/tests/test_defaults.py
@@ -59,3 +59,28 @@ def test_multiple_flag_default(runner):
 
     result = runner.invoke(cli, ["-y", "-n", "-f", "-v", "-q"], standalone_mode=False)
     assert result.return_value == ((True, False), (True,), (1, -1))
+
+
+def test_flag_default_map(runner):
+    """test flag with default map"""
+
+    @click.group()
+    def cli():
+        pass
+
+    @cli.command()
+    @click.option("--name/--no-name", is_flag=True, show_default=True, help="name flag")
+    def foo(name):
+        click.echo(name)
+
+    result = runner.invoke(cli, ["foo"])
+    assert "False" in result.output
+
+    result = runner.invoke(cli, ["foo", "--help"])
+    assert "default: no-name" in result.output
+
+    result = runner.invoke(cli, ["foo"], default_map={"foo": {"name": True}})
+    assert "True" in result.output
+
+    result = runner.invoke(cli, ["foo", "--help"], default_map={"foo": {"name": True}})
+    assert "default: name" in result.output