Repository: clap-rs/clap (language: rust)

Issue:
clap_complete: completions for args following subcommand are missing
### Please complete the following tasks

- [X] I have searched the [discussions](https://github.com/clap-rs/clap/discussions)
- [X] I have searched the [open](https://github.com/clap-rs/clap/issues) and [rejected](https://github.com/clap-rs/clap/issues?q=is%3Aissue+label%3AS-wont-fix+is%3Aclosed) issues

### Rust Version

rustc 1.72.1 (d5c2e9c34 2023-09-13)

### Clap Version

clap: 4.4.4, clap_complete: 4.4.1

### Minimal reproducible code

```rust
fn main() {
    #[derive(Clone, clap::ValueEnum)]
    enum Enum {
        A,
        B,
        C,
    }

    // create a dummy command with a subcommand, which in turn takes an enum arg
    let mut app = clap::Command::new("mre").subcommand(
        clap::Command::new("subcmd").arg(
            clap::Arg::new("arg")
                .required(true)
                .value_parser(clap::builder::EnumValueParser::<Enum>::new()),
        ),
    );

    // ask clap_complete to generate completions for the argument following the subcommand
    let completions = clap_complete::dynamic::complete(
        &mut app,
        vec!["mre".into(), "subcmd".into(), "".into()],
        2,
        None,
    )
    .unwrap();
    // this will panic because 'A', 'B', 'C' are missing (only '-h' and '--help' are listed)
    assert!(completions.len() >= 3);
}
```


### Steps to reproduce the bug with the above code

`cargo run` is enough as long as the `"unstable-dynamic"` is active for `clap_complete`.

### Actual Behaviour

clap_complete doesn't suggest any values for arguments following a subcommand.

### Expected Behaviour

It should suggest possible values for arguments following a subcommand.

### Additional Context

The reason for this seems fairly straight-forward:

The code responsible for adding the arg value completions uses the `pos_index` passed into the function to find the correct `clap::Arg`:

https://github.com/clap-rs/clap/blob/0d9b14fa6e9ccb09fea5d7c93477b7fca8d51bdc/clap_complete/src/dynamic/completer.rs#L150-L155

This fails because the `pos_index` in our example is set to 0. The `pos_index` is always set to 0 when clap_complete encounters a subcommand:

https://github.com/clap-rs/clap/blob/0d9b14fa6e9ccb09fea5d7c93477b7fca8d51bdc/clap_complete/src/dynamic/completer.rs#L64-L68


I fail to see why this is done. If the value is set to 1 instead, the example starts working.

### Debug Output

_No response_


Discussion / hints:

Fix patch:
diff --git a/clap_complete/src/dynamic/completer.rs b/clap_complete/src/dynamic/completer.rs
index cb3b96bbbeb..3813e910a0a 100644
--- a/clap_complete/src/dynamic/completer.rs
+++ b/clap_complete/src/dynamic/completer.rs
@@ -63,7 +63,7 @@ pub fn complete(
         if let Ok(value) = arg.to_value() {
             if let Some(next_cmd) = current_cmd.find_subcommand(value) {
                 current_cmd = next_cmd;
-                pos_index = 0;
+                pos_index = 1;
                 continue;
             }
         }


Test patch:
diff --git a/clap_complete/tests/testsuite/dynamic.rs b/clap_complete/tests/testsuite/dynamic.rs
index 2755f33bd4c..7389713874f 100644
--- a/clap_complete/tests/testsuite/dynamic.rs
+++ b/clap_complete/tests/testsuite/dynamic.rs
@@ -101,6 +101,26 @@ fn suggest_additional_short_flags() {
     );
 }
 
+#[test]
+fn suggest_subcommand_positional() {
+    let mut cmd = Command::new("exhaustive").subcommand(Command::new("hello-world").arg(
+        clap::Arg::new("hello-world").value_parser([
+            PossibleValue::new("hello-world").help("Say hello to the world"),
+            "hello-moon".into(),
+            "goodbye-world".into(),
+        ]),
+    ));
+
+    snapbox::assert_eq(
+        "--help\tPrint help (see more with '--help')
+-h\tPrint help (see more with '--help')
+hello-world\tSay hello to the world
+hello-moon
+goodbye-world",
+        complete!(cmd, "hello-world [TAB]"),
+    );
+}
+
 fn complete(cmd: &mut Command, args: impl AsRef<str>, current_dir: Option<&Path>) -> String {
     let input = args.as_ref();
     let mut args = vec![std::ffi::OsString::from(cmd.get_name())];