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

util: add colorize functionality #43523

Closed
wants to merge 1 commit into from

Conversation

BridgeAR
Copy link
Member

@BridgeAR BridgeAR commented Jun 21, 2022

The colorize object allows to format strings with ansi color codes
so that the string is stylized on a terminal.

This is a utility function that should not yet be exposed to the
users to allow some further polishing first.
This should be exposed under a completely new formatter module instead of adding new functionality to util.
Adding this functionality was discussed at the collaborator summit.

I played around with different builder APIs such as:

new Colorize().bold.green('bold green')
colorize().bold().green('bold green')
colorize.bold.green('bold green')

In the end I went with the latter, especially, due to chalk already using this.

Refs: #43382

Signed-off-by: Ruben Bridgewater ruben@bridgewater.de

@nodejs/util @nodejs/tooling PTAL.

@nodejs-github-bot nodejs-github-bot added debugger Issues and PRs related to the debugger subsystem. needs-ci PRs that need a full CI run. repl Issues and PRs related to the REPL subsystem. util Issues and PRs related to the built-in util module. labels Jun 21, 2022
The colorize object allows to format strings with ansi color codes
so that the string is stylized on a terminal.

This is a utility function that should not yet be exposed to the
users to allow some further polishing first.

Signed-off-by: Ruben Bridgewater <ruben@bridgewater.de>
)

console.log(
colorize.bold.underline.red('bold red underline')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i would definitely prefer to avoid getters; both because it's a more confusing API, and because it's slower. i'd follow colors here, not chalk.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Colors supports this notation? Manipulating the string prototype is not ideal (that's the original colors API).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh no, i meant colors/safe :-) definitely nobody should use the colors style :-)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am somewhat puzzled: that exact API is the one implemented here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, maybe i'm confused. i'd prefer colorize.bold().underline() to colorize.bold.underline, to be clearer.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did consider that as well and I am open to using that, if it's what a majority prefers. Right now I would stick to the existing due to these reasons:

  1. Users of colors and chalk are used to it
  2. Passing a string to only the last call might also be confusing without a .write()/.format() similar function
  3. The performance should pretty much be identical and there should be room for improvement one way or the other (the implementation is already decent performance wise while chalk is still faster)

@Qix-
Copy link

Qix- commented Jun 21, 2022

Can I ask, why are we moving established package functionality from the ecosystem into core? What is the goal by providing this as a standard module?

@ljharb
Copy link
Member

ljharb commented Jun 21, 2022

@Qix- in this particular case, the established packages are not reliable. One has gone ESM-only, and the other was turned into malware by its maintainer.

This is something core should have provided many years ago, but for these packages, and it's now critical it does so, for security and reliability reasons.

added: REPLACEME
-->

The `util.colorize` object provides functions that add ansi color codes to the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The `util.colorize` object provides functions that add ansi color codes to the
The `util.colorize` object provides functions that add ANSI color codes to the

A citation for “ANSI color codes” would be a good addition.

Comment on lines +442 to +444
// TODO(BridgeAR): Consider using a class instead and require the user to instantiate it
// before using to declare their color support (or use a default, if none
// provided).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why wouldn’t or couldn’t these be simple static functions that require no initialization? I mean, aren’t they essentially just prepending and appending \u001b[90m and \u001b[39m and the like?

As a user, I’d prefer they be as terse as possible. I’d be more likely to use them the simpler they are.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes and no: if we add more colors such as hex colors later on, we'll need to check that the terminal does indeed support the colors. Currently there's no way to do this besides a best effort check and we sometimes detect colors when not being supported and the other way around. Therefore I would like to provide a way to define the support by the user:

const { Colorize } = require('formatter')

const colorize256 = new Colorize({ colors: 256 })

console.log(
  colorize256.bold.underline.hex('#123456')('bold underline fancy color')
)

Using Colorize.bold.underline.hex('#123456')('bold underline maybe fancy color') could try to auto detect the supported colors while using the instance would be fixed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These feel like almost two use cases: a simple CLI tool like a test runner that needs only a handful of colors (or only green and red); and a more complicated CLI tool that wants lots of colors. The latter can call some kind of initialization function, since it’s somewhat expected that more work would be required to do something fancy; but ideally the simple case wouldn’t need much ceremony.

});
}

for (const [style, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(inspect.colors))) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to use primordials here? @aduh95

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's not as important at the top level, but it'd probably be a good idea for consistency

@Qix-
Copy link

Qix- commented Jun 22, 2022

One has gone ESM-only, and the other was turned into malware by its maintainer.

What do you expect us to do when the TC-39 introduces fundamental language changes without any migration plan? We put off porting for literal years, and when it became more of a problem not to, now we're being told we're being hostile?

Is Node just going to integrate every popular npm package at once?

@GeoffreyBooth
Copy link
Member

What do you expect us to do

Let's please keep the discussion in this thread focused on the technical details of this PR. If you'd like to debate the feature itself, please open a discussion issue. Product debate on PR threads makes PRs difficult to review.

@F3n67u
Copy link
Member

F3n67u commented Jun 22, 2022

I think if there is any question about adding this feature, we could move to #43382 which @BridgeAR created for this feature.

Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few notes:

  1. what happens if colors are not available in the TTY?
  2. how could somebody override that setting?

I think we should provide a constructor too where this could be configured.

Copy link
Member

@benjamingr benjamingr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#43382 (comment) want to wait for this to conclude

@BridgeAR
Copy link
Member Author

I am closing this for now until we are able to resolve the discussion in #43382

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
debugger Issues and PRs related to the debugger subsystem. needs-ci PRs that need a full CI run. repl Issues and PRs related to the REPL subsystem. util Issues and PRs related to the built-in util module.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants