Skip to content
This repository has been archived by the owner on Jan 1, 2022. It is now read-only.

Ability to style help messages #150

Open
2 tasks done
epage opened this issue Dec 6, 2021 · 26 comments
Open
2 tasks done

Ability to style help messages #150

epage opened this issue Dec 6, 2021 · 26 comments

Comments

@epage
Copy link
Owner

epage commented Dec 6, 2021

Issue by pickfire
Tuesday Apr 07, 2020 at 07:09 GMT
Originally opened as clap-rs/clap#1790


Make sure you completed the following tasks

Describe your use case

Configuration to allows styling help messages. It is helpful for example when styling help messages in a way to improves discover-ability of sub-commands or even bold and emphasize command description, or with the use of colors.

Describe the solution you'd like

It may have cross platform terminal support issue so we may need to depend on some other crates to handle styling for this and it is also better to be feature gated.

A snipped in my mind would be to have some terminal escapes to display the color but it may not be cross-platform, this should be open for discussion.

    .subcommand("\e[1mb\e[muild")

But it should be extensible so it could be reused for man page generation or completions later on.

Alternatives, if applicable

Use other crates to get the same feature

Additional context

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by pksunkara
Tuesday Apr 07, 2020 at 09:00 GMT


What happens currently if you actually use the ansi escape codes in the usage messages right now?

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by pickfire
Wednesday Apr 08, 2020 at 13:29 GMT


@pksunkara Oh, right now the ansi escape codes does not even work.

use clap::{App, SubCommand};

fn main() { Run
    let matches = App::new("app")
        .subcommand(SubCommand::with_name(r"\e[1mt\e[mest"))
        .get_matches();
    dbg!(matches);
}
> cargo r -- -h
   Compiling hello v0.1.0 (/home/ivan/hello)
    Finished dev [unoptimized + debuginfo] target(s) in 0.77s
     Running `target/debug/hello -h`
app

USAGE:
    hello [SUBCOMMAND]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

SUBCOMMANDS:
    \e[1mt\e[mest
    help             Prints this message or the help of the given subcommand(s)

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by Dylan-DPC
Wednesday Apr 08, 2020 at 18:55 GMT


@pickfire hey, thanks for reporting this. do you want to work on this issue? feel free to submit a PR :)

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by pickfire
Friday Apr 10, 2020 at 01:10 GMT


@Dylan-DPC Nope, I will probably not work on this. Maybe I will work on the extra line config #1642.

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by Dylan-DPC
Friday Apr 10, 2020 at 01:12 GMT


@pickfire sure no issues

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by CreepySkeleton
Friday Apr 10, 2020 at 19:58 GMT


Sidenote: on Windows < 10 ascii escape codes are not supported AFAIK. Do we care?

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by mainrs
Thursday Jul 30, 2020 at 11:45 GMT


Wouldn't an API be better that can be passed to items. This would allow for noop implementations on unsupported platforms. There are enough crates out there that already do that, there would just be the need to create an API around it. Maybe something like this?

use clap::{App, SubCommand, Style};

fn main() { Run
    let style = Style::default()
        .fg(Color::Red)
        .bg(Color::Orange)
        .underline();

    let matches = App::new("app")
        .subcommand(SubCommand::with_name("test").style(style))
        .get_matches();
    dbg!(matches);
}

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by pickfire
Thursday Jul 30, 2020 at 17:12 GMT


But how does this API works with some more advanced? Like command description where one needs to change the style of some text partially? I bet it would be complicated.

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by mainrs
Thursday Jul 30, 2020 at 17:26 GMT


I mean there are already solutions for that. For example https://github.com/mackwic/colored allows to color strings how you'd like. And you can just compose them using the format macros.

Given the example above it wasn't clear that a need arised in having everything colorable. And I kind of doubt the usefulness of that one.

Not sure what clap does under the hood to be honest, but I just tested it using a simple example and clap does filter out the ANSI. I did some fast digging but couldn't find the part where it does that. You guys probably know more though.

use clap::{Arg, App};
use colored::Colorize;

fn main() {
    println!("{}", "hello world".red());
    let matches = App::new("test")
        .arg(Arg::with_name("arg")
            .about("some longer description".cyan().as_ref()))
        .get_matches();
}

I expected the above to print the help in cyan, but the control codes get filtered out for some reason. The hello world is red though.

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by pickfire
Friday Jul 31, 2020 at 15:16 GMT


@pksunkara IIRC currently clap filters out ansi escapes codes like @sirwindfield mentioned. I wonder if there is a reason behind it?

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by pksunkara
Friday Jul 31, 2020 at 21:53 GMT


I am not sure if we filter or remove it. I would need to check. But the current behavior you are describing is intentional. Having non display chars was messing with the help message indentation.

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by pickfire
Saturday Aug 01, 2020 at 09:16 GMT


But these escape codes for coloring are not adding any spaces or changing the indentation, maybe we can explicitly whitelist the escape codes for coloring (except those that mess with the cursors).

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by CreepySkeleton
Saturday Aug 01, 2020 at 12:29 GMT


Pasting my own comment from elsewhere


That said, what I'd suggest is some kind of placeholder that resolves to either changing the colour if colourization is enabled or nothing if it's disabled.

I was thinking along these lines in the context of #1790. Something like

{color:yellow:USAGE}

or more generally

{color:color_name-bold:text}
 ----- ---------- ---- ----
 |        |         |
 keyword  |       optional bold switch
       the color

And maintain the list of supported colors.

I don't want to support any RGB-or-something notations because Windows CMD has only a set of predefined colors and implementing the RGB code => winapi color mapping is something I very much like to avoid.

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by pickfire
Saturday Aug 01, 2020 at 12:54 GMT


@CreepySkeleton Does windows support for coloring and codes similar to the one in linux? I wonder if it would be good to do it this way, the API looks interesting but I think it may be a bit limited for linux where people cannot use something special like blinking cursors (I rarely see people using it but it could be done). Or maybe should we still allow an API to let people paste raw text for different platforms or we could pair it with some kind of #[cfg(platform?)] for it?

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by CreepySkeleton
Saturday Aug 01, 2020 at 14:22 GMT


Wait, we were talking about coloring and bolding and italicizing arbitrary parts of the template and then we somehow ended up talking about blinking cursors??? How on earth does this stuff relate to help messages?

As for the question, yes, windows has support for text coloring. Specifically, we use termocolor for cross-platform handing of all this insanity, so I'd say this enum is all you can count on (except Ansi and Rgb, see the reason above).

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by mainrs
Saturday Aug 01, 2020 at 14:35 GMT


That doesn't hold true for all Windows versions. Windows 10 does support RGB values the same as Linux does. I did find and use a crate that had support for it, not sure what it's name was though.

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by pickfire
Saturday Aug 01, 2020 at 15:39 GMT


Wait, we were talking about coloring and bolding and italicizing arbitrary parts of the template and then we somehow ended up talking about blinking cursors??? How on earth does this stuff relate to help messages?

Yes, we are talking about coloring, bolding and italicizing (or maybe underline too). I just wanted to talk about the extensibility which probably we won't need because we are limited to cross platform support but I am just wondering if there is a possibility that we are able allow that.

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by CreepySkeleton
Saturday Aug 01, 2020 at 15:56 GMT


That's all nice and dandy, but let's imagine you're on Windows 7 or 8 or pre-escapes-supported win 10 (was about 35% of market share last time I looked) and you're trying to set the RGB color, say {color:#ef432a:TEXT}. What is clap supposed to do? What can clap do? Only ignore the setting - there's no sane way to map an RGB code to one of the 16 colors and make it look good.

If we implemented RGB handling in the way described above (and I see no others), then we're up to answering questions like, "I (developer) made use of the brand new feature and now my Win 7 users complain they're left staring at black-and-white wall of text, all retro! You claimed support for win 7; is RGB broken?".

This is the reason I'm not excited about RGB: I don't want to roll features that sometimes work and sometimes don't.

Although, I admit I'm not dead set against it, but I'm going to need some further persuasion about why this is useful. Are the 16 colors not enough for help messages?

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by mainrs
Saturday Aug 01, 2020 at 16:25 GMT


I do get your point, but what is wrong with having the developer decide if they want to map the RGB colors back to the 16 if needs arises due to platform restrictions? I guess for a first implementation RGB can be ignored for sure. But I don't see why this couldn't even be an optional feature people can opt in to.

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by CreepySkeleton
Saturday Aug 01, 2020 at 16:46 GMT


Hm, I guess what we need is some sort of (optional) fallback: {color:#ef432a(yellow):TEXT} which means "if the platform does not support rgb, set it to yellow". If no fallback specified, you're out of luck and colors.

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by pksunkara
Tuesday Aug 11, 2020 at 01:01 GMT


I like the format that is proposed but I am also vary about adding DSL's to the descriptions.

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by ajeetdsouza
Tuesday Apr 27, 2021 at 20:40 GMT


@pksunkara instead of a DSL, perhaps users can supply after_help_pieces: Vec<(String, Option<Color>)>? That way, you can just pass it to the Colorizer the same way other strings in clap are passed.

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by lilyball
Monday Jun 28, 2021 at 21:24 GMT


I want color in messages, but primarily I want to be able to just match clap's existing colors rather than specifying a particular one. My use case is when writing a help message for an option with possible/default values. Clap will include these possible/default values in the help string with colors, but if I'm referencing a possible value in the string itself, I want to use the same color. Similarly if I hide the default/possible values I want to be able to reproduce them in the help string.

Basically, what I want is to be able to write arg.hide_default_value(true).hide_possible_values(true).help(…) and still be able to replicate precisely the same output clap does by default. The goal of course is to then modify that, but if I can replicate it, then that means I have the tools to do what I need.

Technically I can do this today in clap 2.33 by using the undocumented clap::Format, but I'm assuming it's undocumented for a reason and a cursory look at clap 3.0 suggests it's no longer available there.

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by lilyball
Monday Jun 28, 2021 at 21:41 GMT


To expand on that, I would really like 3.0 to at least have the ability to apply the same coloration used for the default/possible values, regardless of any support for a full DSL for coloration. At the moment I am going ahead and using clap::Format in my code, with the expectation that I'll have to adapt once clap 3.0 is out and we switch to it, and I'd really love to have some solution that doesn't involve reimporting atty and ansi_term myself.

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by ajeetdsouza
Tuesday Jun 29, 2021 at 07:23 GMT


My use case is that I'd like to show environment variables in the --help menu.

ENVIRONMENT VARIABLES:
    SAMPLE_FOO    This does foo thing.
    SAMPLE_BAR    This does bar thing.

I'd like a way to highlight the heading and items in this list the same way that clap does for flags and options.

@epage
Copy link
Owner Author

epage commented Dec 6, 2021

Comment by epage
Friday Oct 29, 2021 at 20:41 GMT


#2914 is another way of resolving some of the care-abouts mentioned this thread.

Personally, this thread sounds like its pulling into claps' API a terminal styling API, directly or through a template language. There are enough care-abouts and concerns with those APIs, I'm concerned having a bespoke styling API is a bigger concern than we should take on. We could adopt an existing one but those tend to have their own cadence for breaking changes, I'm unsure how much we want to tie ourselves to them in that way.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

1 participant