Giter VIP home page Giter VIP logo

Comments (5)

Timmmm avatar Timmmm commented on May 29, 2024

Same as #121. :-/

from argh.

Timmmm avatar Timmmm commented on May 29, 2024

I had a little look into the code. I think there are two issues:

  1. The docstring is concatenated into one big string ignoring newlines. See this code:

    syn::LitStr::new(&(previous.value() + &*lit_str.value()), previous_span)

  2. The printing code doesn't work quite right even if you do have newlines in the input. See this code.

Here is that code extracted with some example input.

The second issue is easy to solve. The first is more difficult because it isn't obvious when you want newlines. E.g. in this case you clearly do:

Can be one of
* A
* B
* C

But here you probably don't

There are many things
this can be including A,
B and C.

I vaguely recall some other argument parse "solving" this by letting you put {n} for a newline, but I'm not sure I really like that. I think maybe we could get something good with one simple trick.

  1. Any line that starts with [A-Za-z] is appended to the previous line, unless the end of the output is currently \n\n (i.e. a blank line).

I think that would correctly format something like this:

This bit is prose and should
be wrapped into a paragraph.

But this is another paragraph so there
should be a new line between
them.

1. A list would work as expected.
3. Even with long
   entries like this though they
   won't be wrapped nicely.

| Tables | Should |
|------|------|
| Also be | Fine |

I'll try it out.

from argh.

Timmmm avatar Timmmm commented on May 29, 2024

Ok the logic turned out to be slightly more complicated than I thought, but this seems to work:

fn parse_comment(lines: &[&str]) -> String {
    let mut out = String::new();
    for line in lines {
        let line_starts_with_letter = line.bytes().next().map(|c| c.is_ascii_alphabetic()).unwrap_or(false);
        if line_starts_with_letter {
            if !out.is_empty() {
                if out.ends_with('\n') {
                    out.push('\n');
                } else {
                    out.push(' ');
                }
            }
        } else {
            out.push('\n');
        }
        
        out.push_str(line);
    }
    out
}

fn main() {
    let comment = "This bit is prose and should
be wrapped into a paragraph.

But this is another paragraph so there
should be a new line between
them.

1. A list would work as expected.
3. Even with long
   entries like this though they
   won't be wrapped nicely.

| Tables | Should |
|------|------|
| Also be | Fine |";

    let description = parse_comment(&comment.lines().collect::<Vec<_>>());
    
    println!("{}", description);
}

Output:

This bit is prose and should be wrapped into a paragraph.

But this is another paragraph so there should be a new line between them.

1. A list would work as expected.
3. Even with long
   entries like this though they
   won't be wrapped nicely.

| Tables | Should |
|------|------|
| Also be | Fine |

Note the paragraphs are joined together into one line but the other bits aren't.

Now just to fix the printing code...

from argh.

Timmmm avatar Timmmm commented on May 29, 2024

Ok that turned out to be easy - just loop through the lines in the description:

    for line in cmd.description.lines() {
        let mut words = line.split(' ').peekable();
        while let Some(first_word) = words.next() {
            indent_description(&mut current_line);
            current_line.push_str(first_word);
    
            while let Some(&word) = words.peek() {
                if (char_len(&current_line) + char_len(word) + 1) > WRAP_WIDTH {
                    new_line(&mut current_line, out);
                    break;
                } else {
                    // advance the iterator
                    let _ = words.next();
                    current_line.push(' ');
                    current_line.push_str(word);
                }
            }
        } 
        new_line(&mut current_line, out);
    }

Output is:

  target            This bit is prose and should be wrapped into a paragraph.
                    
                    But this is another paragraph so there should be a new line
                    between them.
                    
                    1. A list would work as expected.
                    3. Even with long
                       entries like this though they
                       won't be wrapped nicely.
                    
                    | Tables | Should |
                    |------|------|
                    | Also be | Fine |

Note the first two paragraphs have been reflowed but everything else is left as is.

Full demo here.

I will prepare a PR if somebody from the project says they would accept it.

from argh.

Timmmm avatar Timmmm commented on May 29, 2024

Actually I went ahead and did it because I can use it without waiting for a PR to be accepted. Just add this to your Cargo.toml:

[patch.crates-io]
argh = { git = "https://github.com/Timmmm/argh", branch = "multiline_docs" }

from argh.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.