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

256 color support? #20

Closed
ccheever opened this issue May 23, 2014 · 4 comments
Closed

256 color support? #20

ccheever opened this issue May 23, 2014 · 4 comments

Comments

@ccheever
Copy link

I made a drop-in replacement for chalk that has 256 color support and a few other things.
https://github.com/ccheever/chalk256

Are you interested in adding any of that to chalk? I can create a pull request, but would have to do a bunch of work to make the code match your style, etc., so wanted to ask before putting in the time.

@sindresorhus
Copy link
Member

Nice. I considered adding 256 colors a few months ago, but realized I've never had a need for it, so I didn't want to complicate Chalk with it. Makes much more sense to be in a separate module like yours :)

Do let me know if there's any other way Chalk could improve though.

You say it's a drop-in replacement, but there are several differences. Like you use lowercase for bgRed.

Sidenote: Would love to get some help on #16. We could both benefit from that ;)

@ccheever
Copy link
Author

FWIW - bgRedis there also. There are a few collisions between the CSS color names on the 256 color palette and the basic system color palette -- red is one of these, and so bgRed and bgred cause different ANSI codes to be used. Depending on your settings, they will probably look the same, but if you mess with your terminal settings, they could look different. In any case, I'm pretty anywhere you use chalk, chalk256 should work as a drop-in replacement. I don't love having bgred and bgRed mean almost the same but slightly different things so will probably clean that up later.

I'll take a look at #16 but don't have any immediate ideas.

@ccheever
Copy link
Author

re: #16 & #21.
I rewrote the entire module that I wrote before. The code is much cleaner now and the performance is very good. I'm pretty happy with the API.

https://github.com/aceface/crayon

Here is the simple benchmark I made and the results of running it:

ccheever@Charlies-MacBook-Air:~/tmp$cat colorbench.coffee

n = 100000
modules = ['chalk', 'crayon']

for iter in [0...3]
  for m in modules
    console.log "Running #{ m } #{ n } times"
    console.time "require-#{ m }"
    cm = require m
    console.timeEnd "require-#{ m }"
    console.time cm.blue m

    for i in [0...n]
      cm.red "A string that is about 80 characters long (normal use I think?)"

    console.timeEnd cm.blue m
ccheever@Charlies-MacBook-Air:~/tmp$node colorbench.js
Running chalk 100000 times
require-chalk: 6ms
chalk: 4303ms
Running crayon 100000 times
require-crayon: 8ms
crayon: 175ms
Running chalk 100000 times
require-chalk: 0ms
chalk: 4161ms
Running crayon 100000 times
require-crayon: 0ms
crayon: 176ms
Running chalk 100000 times
require-chalk: 0ms
chalk: 4320ms
Running crayon 100000 times
require-crayon: 0ms
crayon: 198ms
ccheever@Charlies-MacBook-Air:~/tmp$

The performance problems with chalk are mostly because each time you get a property on it, like chalk.red, you end up making a new function and then defining a bunch of dynamic properties on it. That whole process is pretty expensive. The main thing that makes crayon much faster is that every time it does that, it stores the function it just created so it doesn't have to create it again. Since people are very likely to call a module like this with the same arguments over and over again, I think this is probably meaningful in the real world as well.

The function creation and definition of all the properties is a much, much bigger deal than Array.slice vs [].slice. I experimented a little bit with crayon and changing that to not do an Array creation or slice which will copy the arguments array basically doesn't make much of a difference at all. v8 seems to optimize that really well since it must be quite common -- it may not even actually make a copy of the arguments Array since it isn't mutated.

One very small difference in crayon vs chalk is that I used util.format instead of just joining on a space. I think its nicer and more closely matches what a user would want. Ex:

coffee> console.log util.format {1:2}
{ '1': 2 }
undefined
coffee> console.log [{1:2}].join ' '
[object Object]
undefined

util.format is a little bit more expensive; switching to joining on a space would shave ~20ms off the benchmark time for color, but I think its worth it. In any case, the main thing that is chalk's performance problem is just that you don't want to make a new function every time you call chalk.blue or similar and even worse, doing an Object.defineProperty on it for every possible style.

@sindresorhus
Copy link
Member

Thanks for looking into this @ccheever :)

I'll see what I can do to optimize Chalk.

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

No branches or pull requests

2 participants