cli icon indicating copy to clipboard operation
cli copied to clipboard

Variants of `col_` and `style_` functions that return bare strings

Open lionel- opened this issue 1 year ago • 3 comments

The attributes of cli_ansi_string are a bit cumbersome for programming, they end up in unexpected places and cause issues for comparison, testing, etc.

These variants could be suffixed with _bare()? We use the term "bare" in rlang and purrr for objects without attributes.

lionel- avatar Aug 16 '22 12:08 lionel-

You mean the class attribute? You can call as.character() to drop that:

❯ attributes(col_red("red"))
$class
[1] "cli_ansi_string" "ansi_string"     "character"

❯ as.character(col_red("red"))
[1] "\033[31mred\033[39m"

gaborcsardi avatar Aug 16 '22 13:08 gaborcsardi

yes and the extra step either: makes it less likely to remember to remove the class; or makes the code harder to read.

lionel- avatar Aug 16 '22 13:08 lionel-

Maybe so, but adding _bare to all such functions will create ~60 more functions, which does not seem like a good idea, either.

gaborcsardi avatar Aug 16 '22 13:08 gaborcsardi

Lots of packages add similar classes, e.g. glue. I think if the class attribute is in the way of snapshot tests, then we would ideally improve the snapshot tests.

gaborcsardi avatar Aug 18 '22 14:08 gaborcsardi

yes and the glue class has been occasionally getting in the way as well. It's especially important not to leak these attributes when returning objects to users. Otherwise the returned class depends on implementation details.

How about a "col" and "style" constructor that would take enums of colour and styles? Then we'd only have 2 more functions.

lionel- avatar Aug 18 '22 15:08 lionel-

Still, it is not a good idea to have extra exported functions, that essentially duplicate the functionality of the package, but behave differently. If you don't want the class in rlang, you can write a helper function that wraps cli functions, and drops it?

gaborcsardi avatar Aug 18 '22 15:08 gaborcsardi

yes that is indeed what I did. I think it's strange that cli does not provide core/primitive functions (I don't see them as extra) to implement core behaviour without returning interactivity-facing classes. I can see we have a disagreement about API design so I'm closing this.

lionel- avatar Aug 18 '22 15:08 lionel-

I think it is often better to provide a single api for task in a package. There is value in having a single way to do a task, at least with a certain package.

In general I do see the value in implementing things using "primitive" functions (see e.g. the very un-magical way callr::r() takes an expression, which I am more and more happy with). But my feeling is that the current issues with ansi_string do not warrant another API. I would hate to confuse people wrt which api to use when, and I suspect that I would also hate maintaining the two apis. Considering how much we use glue, and that glue also returns a classed string, and does not have a primitive method, makes me think that we can overcome the issues.

This said, I personally somewhat regret adding the ansi_string class to cli. crayon does not have a class, and I added it to cli after requests from colleagues.

gaborcsardi avatar Aug 18 '22 19:08 gaborcsardi