Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Potential bug with new lines in the help output when markdown mode is used #447

Open
7 tasks done
renardeinside opened this issue Aug 21, 2022 · 7 comments · May be fixed by #815
Open
7 tasks done

Potential bug with new lines in the help output when markdown mode is used #447

renardeinside opened this issue Aug 21, 2022 · 7 comments · May be fixed by #815
Labels
bug Something isn't working p2

Comments

@renardeinside
Copy link

renardeinside commented Aug 21, 2022

First Check

  • I added a very descriptive title to this issue.
  • I used the GitHub search to find a similar issue and didn't find it.
  • I searched the Typer documentation, with the integrated search.
  • I already searched in Google "How to X in Typer" and didn't find any information.
  • I already read and followed all the tutorial in the docs and didn't find an answer.
  • I already checked if it is not related to Typer but to Click.

Commit to Help

  • I commit to help with one of those options 👆

Example Code

import typer

app = typer.Typer(rich_markup_mode="markdown", name="tester-app")

@app.command(name="tester-cmd", help="""
    Header

    Line 1
    Line 2
    Line 3
""")
def cmd():
    pass

if __name__ == "__main__":
    app()

Description

  • Create the typer application as above
  • Run this application with --help switch
  • Lines are not properly formatted (they don't start from a newline):

Input:

> tester-app tester-cmd --help

Output:

 Usage: dbx tester-cmd [OPTIONS]                                                                                                                                            
                                                                                                                                                                            
Header                                                                                                                                                                     
Line 1 Line 2 Line 3     

Expected output:

Header                                                                                                                                                                     
Line 1 
Line 2
Line 3     

If I run the same command with: app = typer.Typer(rich_markup_mode="rich", name="tester-app")

I get the expected result:

 Header                                                                                                                                                                     
 Line 1                                                                                                                                                                     
 Line 2                                                                                                                                                                     
 Line 3   

If I add more newlines in markdown mode, I get the following:
Input:

@app.command(name="tester-cmd", help="""
    Header

    Line 1

    Line 2

    Line 3
""")
def cmd():
    pass        

Output:

 Header                                                                                                                                                                     
 Line 1 Line 2 Line 3 

It only works if I add 3 newlines:
Input:

@app.command(name="tester-cmd", help="""
    Header

    Line 1



    Line 2



    Line 3
""")
def cmd():
    pass

Output:

 Header                                                                                                                                                                     
 Line 1                                                                                                                                                                     
                                                                                                                                                                            
 Line 2                                                                                                                                                                     
                                                                                                                                                                            
 Line 3 

But it's also not the desired output. Desired output would be something similar to rich formatting:

 Header                                                                                                                                                                     
 Line 1                                                                                                                                                                     
 Line 2                                                                                                                                                                     
 Line 3   

Operating System

macOS

Operating System Details

Apple M1, macOs Monterey 12.2.1

Typer Version

0.6.1

Python Version

Python 3.9.12

Additional Context

No response

@renardeinside renardeinside added the question Question or problem label Aug 21, 2022
@renardeinside
Copy link
Author

renardeinside commented Aug 24, 2022

For those who were running into the same issue, here is a quick monkey patch I've prepared:

  1. add the custom output formatter:
import inspect
from typing import Union, Iterable

import click
from rich.console import group
from rich.markdown import Markdown
from rich.text import Text
from typer.core import MarkupMode
from typer.rich_utils import MARKUP_MODE_MARKDOWN, STYLE_HELPTEXT_FIRST_LINE, _make_rich_rext


@group()
def _get_custom_help_text(
    *,
    obj: Union[click.Command, click.Group],
    markup_mode: MarkupMode,
) -> Iterable[Union[Markdown, Text]]:
    # Fetch and dedent the help text
    help_text = inspect.cleandoc(obj.help or "")

    # Trim off anything that comes after \f on its own line
    help_text = help_text.partition("\f")[0]

    # Get the first paragraph
    first_line = help_text.split("\n\n")[0]
    # Remove single linebreaks
    if markup_mode != MARKUP_MODE_MARKDOWN and not first_line.startswith("\b"):
        first_line = first_line.replace("\n", " ")
    yield _make_rich_rext(
        text=first_line.strip(),
        style=STYLE_HELPTEXT_FIRST_LINE,
        markup_mode=markup_mode,
    )

    # Get remaining lines, remove single line breaks and format as dim
    remaining_paragraphs = help_text.split("\n\n")[1:]
    if remaining_paragraphs:
        remaining_lines = inspect.cleandoc("\n\n".join(remaining_paragraphs).replace("<br/>", "\\"))
        yield _make_rich_rext(
            text=remaining_lines,
            style="cyan",
            markup_mode=markup_mode,
        )
  1. Monkey-patch the original method before initializing the app object:
import typer.rich_utils

typer.rich_utils._get_help_text = _get_custom_help_text

This allows you to use <br/> tag , which is recognized by other markdown readers, for example by mkdocs-click.

Some output limitations of the method above:

  • <br/> can only be specified in command help, this method won't work in arguments/options help strings
  • <br/> shall only be specified once and and the end of the string that is followed by a non-empty line.

@jhamman
Copy link

jhamman commented Dec 17, 2022

We've also just run into this issue. Markdown that is rendered correctly by Rich is not rendered correctly when fed through a Typer docstring. @renardeinside's monkeypatch may work but a proper fix would be much more palatable.

@jaklan
Copy link

jaklan commented Dec 27, 2022

One more bump, it makes the Markdown mode not really usable unfortunately.

@MartinSoto
Copy link

It's now over a year since this problem was reported and Markdown support remains completely broken. Is this library abandonware by now? It'd be a real pity.

@demizer
Copy link

demizer commented Dec 15, 2023

+1 for #671 to get merged. This is a real bummer when using rich and markdown in help docs.

@benrhodes26
Copy link

Yeah, would love to see a fix for this!

@svlandeg
Copy link
Member

svlandeg commented Feb 29, 2024

Is this library abandonware by now?

It isn't 🙂. Open-source maintenance is quite a bit of work, and we're facing some backlog, but we're still committed to maintaining and improving typer. In the next few months, we hope to be making more progress on that backlog.

Thanks all for your comments & contributions, they're very much appreciated!

gar1t added a commit to gar1t/typer that referenced this issue Apr 30, 2024
gar1t added a commit to gar1t/typer that referenced this issue Apr 30, 2024
Includes fix to typo in function name.

Ref: fastapi#447
gar1t added a commit to gar1t/typer that referenced this issue Apr 30, 2024
Includes fix to typo in function name.

Ref: fastapi#447
@gar1t gar1t linked a pull request Apr 30, 2024 that will close this issue
@svlandeg svlandeg added bug Something isn't working p2 and removed question Question or problem labels May 21, 2024
@svlandeg svlandeg linked a pull request May 21, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working p2
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants