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

Issue:
wrap_help can fail to wrap at the correct point
### 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.70.0 (90c541806 2023-05-31) (built from a source tarball)

### Clap Version

4.3.16

### Minimal reproducible code

```rust
use clap::{Parser, ValueEnum};

#[derive(Debug, Parser)]
struct Cli {
    #[arg(short)]
    foo: Foo,
}

#[derive(Clone, Debug, ValueEnum)]
enum Foo {
    /// Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
    /// ut labore et dolore magna aliqua. Sed vulputate mi sit amet mauris commodo quis imperdiet
    /// massa.
    Foo,
}

fn main() {
    let cli = Cli::parse();
    println!("{cli:?}");
}
```

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

Set your terminal to 90 columns, for example, then:

```
cargo run -- --help
```

### Actual Behaviour

Output (manually hard-wrapped for sake of demonstration):
```
Usage: example -f <FOO>

Options:
  -f <FOO>
          Possible values:
          - foo: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod t
empor
            incididunt ut labore et dolore magna aliqua. Sed vulputate mi sit amet mauris
            commodo quis imperdiet massa

  -h, --help
          Print help (see a summary with '-h')
```

### Expected Behaviour

Output:
```
Usage: example -f <FOO>

Options:
  -f <FOO>
          Possible values:
          - foo: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
            tempor incididunt ut labore et dolore magna aliqua. Sed vulputate mi sit amet
            mauris commodo quis imperdiet massa

  -h, --help
          Print help (see a summary with '-h')
```

### Additional Context

Tested in Zsh 5.8.1 and Bash 5.1.16, both running inside and outside Tmux 3.2a.

### Debug Output

```
[clap_builder::builder::command]Command::_do_parse
[clap_builder::builder::command]Command::_build: name="example"
[clap_builder::builder::command]Command::_propagate:example
[clap_builder::builder::command]Command::_check_help_and_version:example expand_help_tree=false
[clap_builder::builder::command]Command::long_help_exists
[clap_builder::builder::command]Command::_check_help_and_version: Building default --help
[clap_builder::builder::command]Command::_propagate_global_args:example
[clap_builder::builder::debug_asserts]Command::_debug_asserts
[clap_builder::builder::debug_asserts]Arg::_debug_asserts:foo
[clap_builder::builder::debug_asserts]Arg::_debug_asserts:help
[clap_builder::builder::debug_asserts]Command::_verify_positionals
[clap_builder::parser::parser]Parser::get_matches_with
[clap_builder::parser::parser]Parser::get_matches_with: Begin parsing '"--help"'
[clap_builder::parser::parser]Parser::possible_subcommand: arg=Ok("--help")
[clap_builder::parser::parser]Parser::get_matches_with: sc=None
[clap_builder::parser::parser]Parser::parse_long_arg
[clap_builder::parser::parser]Parser::parse_long_arg: Does it contain '='...
[clap_builder::parser::parser]Parser::parse_long_arg: Found valid arg or flag '--help'
[clap_builder::parser::parser]Parser::parse_long_arg("help"): Presence validated
[clap_builder::parser::parser]Parser::react action=Help, identifier=Some(Long), source=CommandLine
[clap_builder::parser::parser]Help: use_long=true
[clap_builder::builder::command]Command::long_help_exists: true
[clap_builder::builder::command]Command::write_help_err: example, use_long=true
[clap_builder::builder::command]Command::long_help_exists: true
[  clap_builder::output::help]write_help
[clap_builder::output::help_template]HelpTemplate::new cmd=example, use_long=true
[clap_builder::output::help_template]should_show_arg: use_long=true, arg=foo
[clap_builder::output::help_template]HelpTemplate::write_templated_help
[clap_builder::output::help_template]HelpTemplate::write_before_help
[ clap_builder::output::usage]Usage::create_usage_no_title
[ clap_builder::output::usage]Usage::create_help_usage; incl_reqs=true
[ clap_builder::output::usage]Usage::needs_options_tag
[ clap_builder::output::usage]Usage::needs_options_tag:iter: f=foo
[ clap_builder::output::usage]Usage::needs_options_tag:iter Option is required
[ clap_builder::output::usage]Usage::needs_options_tag:iter: f=help
[ clap_builder::output::usage]Usage::needs_options_tag:iter Option is built-in
[ clap_builder::output::usage]Usage::needs_options_tag: [OPTIONS] not required
[ clap_builder::output::usage]Usage::get_args: incls=[]
[ clap_builder::output::usage]Usage::get_args: unrolled_reqs=["foo"]
[ clap_builder::output::usage]Usage::get_args: ret_val=[StyledStr("\u{1b}[1m-f\u{1b}[0m <FOO>")]
[ clap_builder::output::usage]Usage::create_help_usage: usage=example -f <FOO>
[clap_builder::output::help_template]HelpTemplate::write_all_args
[clap_builder::output::help_template]should_show_arg: use_long=true, arg=foo
[clap_builder::output::help_template]should_show_arg: use_long=true, arg=help
[clap_builder::output::help_template]HelpTemplate::write_args Options
[clap_builder::output::help_template]should_show_arg: use_long=true, arg=foo
[clap_builder::output::help_template]HelpTemplate::write_args: arg="foo" longest=8
[clap_builder::output::help_template]should_show_arg: use_long=true, arg=help
[clap_builder::output::help_template]HelpTemplate::write_args: arg="help" longest=8
[clap_builder::output::help_template]should_show_arg: use_long=true, arg=foo
[clap_builder::output::help_template]HelpTemplate::spec_vals: a=-f <FOO>
[clap_builder::output::help_template]HelpTemplate::spec_vals: a=-f <FOO>
[clap_builder::output::help_template]HelpTemplate::short
[clap_builder::output::help_template]HelpTemplate::long
[clap_builder::output::help_template]HelpTemplate::align_to_about: arg=foo, next_line_help=true, longest=8
[clap_builder::output::help_template]HelpTemplate::align_to_about: printing long help so skip alignment
[clap_builder::output::help_template]HelpTemplate::help
[clap_builder::output::help_template]HelpTemplate::help: Next Line...true
[clap_builder::output::help_template]HelpTemplate::help: help_width=10, spaces=0, avail=80
[clap_builder::output::help_template]HelpTemplate::help: Found possible vals...[PossibleValue { name: "foo", help: Some(StyledStr("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Sed vulputate mi sit amet mauris commodo quis imperdiet massa")), aliases: [], hide: false }]
[clap_builder::output::help_template]HelpTemplate::help: Possible Value help
[clap_builder::output::help_template]HelpTemplate::spec_vals: a=--help
[clap_builder::output::help_template]HelpTemplate::short
[clap_builder::output::help_template]HelpTemplate::long
[clap_builder::output::help_template]HelpTemplate::align_to_about: arg=help, next_line_help=true, longest=8
[clap_builder::output::help_template]HelpTemplate::align_to_about: printing long help so skip alignment
[clap_builder::output::help_template]HelpTemplate::help
[clap_builder::output::help_template]HelpTemplate::help: Next Line...true
[clap_builder::output::help_template]HelpTemplate::help: help_width=10, spaces=36, avail=80
[clap_builder::output::help_template]HelpTemplate::write_after_help
[clap_builder::builder::command]Command::color: Color setting...
[clap_builder::builder::command]Auto
[clap_builder::builder::command]Command::color: Color setting...
[clap_builder::builder::command]Auto
```


Discussion / hints:
For a full reproduction case:
`````rust
#!/usr/bin/env nargo
/*!
```cargo
[dependencies]
clap = { version = "4", features = ["derive", "wrap_help"] }
```
*/

use clap::{Parser, ValueEnum};

#[derive(Debug, Parser)]
struct Cli {
    #[arg(short)]
    foo: Foo,
}

#[derive(Clone, Debug, ValueEnum)]
enum Foo {
    /// Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
    /// ut labore et dolore magna aliqua. Sed vulputate mi sit amet mauris commodo quis imperdiet
    /// massa.
    Foo,
}

fn main() {
    let cli = Cli::parse();
    println!("{cli:?}");
}
`````
(`nargo` is just a shell script around `cargo` that enables the nightly feature for this)

Fix patch:
diff --git a/clap_builder/src/output/help_template.rs b/clap_builder/src/output/help_template.rs
index 1ed16da7b9e..da2e7541328 100644
--- a/clap_builder/src/output/help_template.rs
+++ b/clap_builder/src/output/help_template.rs
@@ -701,32 +701,33 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> {
                 self.writer.push_str("Possible values:");
                 for pv in possible_vals.iter().filter(|pv| !pv.is_hide_set()) {
                     let name = pv.get_name();
+
+                    let mut descr = StyledStr::new();
                     let _ = write!(
-                        self.writer,
-                        "\n{:spaces$}- {}{name}{}",
-                        "",
+                        &mut descr,
+                        "{}{name}{}",
                         literal.render(),
                         literal.render_reset()
                     );
                     if let Some(help) = pv.get_help() {
                         debug!("HelpTemplate::help: Possible Value help");
-
                         // To align help messages
-                        let padding = longest - display_width(pv.get_name());
-                        let _ = write!(self.writer, ": {:padding$}", "");
-
-                        let avail_chars = if self.term_w > trailing_indent.len() {
-                            self.term_w - trailing_indent.len()
-                        } else {
-                            usize::MAX
-                        };
-
-                        let mut help = help.clone();
-                        help.replace_newline_var();
-                        help.wrap(avail_chars);
-                        help.indent("", &trailing_indent);
-                        self.writer.push_styled(&help);
+                        let padding = longest - display_width(name);
+                        let _ = write!(&mut descr, ": {:padding$}", "");
+                        descr.push_styled(help);
                     }
+
+                    let avail_chars = if self.term_w > trailing_indent.len() {
+                        self.term_w - trailing_indent.len()
+                    } else {
+                        usize::MAX
+                    };
+                    descr.replace_newline_var();
+                    descr.wrap(avail_chars);
+                    descr.indent("", &trailing_indent);
+
+                    let _ = write!(self.writer, "\n{:spaces$}- ", "",);
+                    self.writer.push_styled(&descr);
                 }
             }
         }


Test patch:
diff --git a/tests/builder/help.rs b/tests/builder/help.rs
index fda7a9aeb13..de13fe048b8 100644
--- a/tests/builder/help.rs
+++ b/tests/builder/help.rs
@@ -449,13 +449,15 @@ Usage: test [OPTIONS]
 Options:
       --possible-values <possible_values>
           Possible values:
-          - short_name: Long enough help message, barely warrant wrapping
+          - short_name: Long enough help message, barely warrant
+            wrapping
           - second:     Short help gets handled the same
 
       --possible-values-with-new-line <possible_values_with_new_line>
           Possible values:
-          - long enough name to trigger new line: Really long enough help message to clearly warrant
-            wrapping believe me
+          - long enough name to trigger new line: Really long
+            enough help message to clearly warrant wrapping believe
+            me
           - second
 
       --possible-values-without-new-line <possible_values_without_new_line>