Repository: pallets/click (python)

Issue:
Required arguments are omitted from command help synopsis
I have a `@click.group` that requires an argument.

The help text of the group itself correctly says `Usage: p.py [OPTIONS] NAME COMMAND [ARGS]...`. However, the help text of the subcommand omits `NAME` which confuses my users.

Example code:

```python
#!/usr/bin/python3

import click

@click.group()
@click.argument("name")
@click.pass_context
def main(ctx, name):
    ctx.obj = dict(name=name)

@main.command()
@click.pass_obj
def cmd(obj):
    print("Running CMD for %s" % (obj['name']))

if __name__ == "__main__":
    main()
```

Output:
```
$ python3 /tmp/p.py test cmd 
Running CMD for test
$ python3 /tmp/p.py --help
Usage: p.py [OPTIONS] NAME COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  cmd
$ python3 /tmp/p.py test cmd --help
Usage: p.py cmd [OPTIONS]

Options:
  --help  Show this message and exit.
$ 
```

I would expect the latter output to be
```
Usage: p.py NAME cmd [OPTIONS]
```

### Environment

* Python version: 3.any
* Click version: 7.0


Pull request:
include mandatory parent arguments in help synposis
Help synopsis of subcommands now include parent's required arguments
example:
```
Usage: cmd ARG subcmd [OPTIONS]
```
fixes #1475 




Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index 79ae5d8..2900361 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -35,6 +35,8 @@ Unreleased
     values from environment variables and defaults. :issue:`729`
 -   Detect the program name when executing a module or package with
     ``python -m name``. :issue:`1603`
+-   Include required parent arguments in help synopsis of subcommands.
+    :issue:`1475`
 
 
 Version 7.1.2
diff --git a/src/click/core.py b/src/click/core.py
index 52f9cac..71178dc 100644
--- a/src/click/core.py
+++ b/src/click/core.py
@@ -508,7 +508,10 @@ class Context:
         if self.info_name is not None:
             rv = self.info_name
         if self.parent is not None:
-            rv = f"{self.parent.command_path} {rv}"
+            parent_command_path = [self.parent.command_path]
+            for param in self.parent.command.get_params(self):
+                parent_command_path.extend(param.get_usage_pieces(self))
+            rv = f"{' '.join(parent_command_path)} {rv}"
         return rv.lstrip()
 
     def find_root(self):


Test patch:
diff --git a/tests/test_arguments.py b/tests/test_arguments.py
index 445b880..ca2e406 100644
--- a/tests/test_arguments.py
+++ b/tests/test_arguments.py
@@ -328,3 +328,44 @@ def test_nargs_default(runner, value, code, output):
     result = runner.invoke(cmd)
     assert result.exit_code == code
     assert output in result.output
+
+
+def test_subcommand_help(runner):
+    @click.group()
+    @click.argument("name")
+    @click.argument("val")
+    @click.option("--opt")
+    @click.pass_context
+    def cli(ctx, name, val, opt):
+        ctx.obj = dict(name=name, val=val)
+
+    @cli.command()
+    @click.pass_obj
+    def cmd(obj):
+        click.echo(f"CMD for {obj['name']} with value {obj['val']}")
+
+    result = runner.invoke(cli, ["foo", "bar", "cmd", "--help"])
+    assert not result.exception
+    assert "Usage: cli NAME VAL cmd [OPTIONS]" in result.output
+
+
+def test_nested_subcommand_help(runner):
+    @click.group()
+    @click.argument("arg1")
+    @click.option("--opt1")
+    def cli(arg1, opt1):
+        pass
+
+    @cli.group()
+    @click.argument("arg2")
+    @click.option("--opt2")
+    def cmd(arg2, opt2):
+        pass
+
+    @cmd.command()
+    def subcmd():
+        click.echo("subcommand")
+
+    result = runner.invoke(cli, ["arg1", "cmd", "arg2", "subcmd", "--help"])
+    assert not result.exception
+    assert "Usage: cli ARG1 cmd ARG2 subcmd [OPTIONS]" in result.output