Powerlevel9k / powerlevel9k

Powerlevel9k was a tool for building a beautiful and highly functional CLI, customized for you. P9k had a substantial impact on CLI UX, and its legacy is now continued by P10k.
https://github.com/romkatv/powerlevel10k
MIT License
13.47k stars 946 forks source link

truncate_with_package_name sometimes grabs the wrong name #350

Closed fracmak closed 7 years ago

fracmak commented 7 years ago

If the repo "name" isn't the first name in the package.json file, it'll print out the wrong name.

Example:

https://github.com/gajus/babel-plugin-react-css-modules/blob/master/package.json

spits out "Gajus Kuizinas" as the project name instead of "babel-plugin-react-css-modules"

bhilburn commented 7 years ago

Not knowing much about package.json files myself, I'm not sure of the best way to handle this.

Any thoughts from our JS devs?

V1rgul commented 7 years ago

It was done this way to avoid external dependencies or firing up an interpreter.
It could be done with a regular expression, but it will either:

Using a complex RegExp supporting all cases will surely be cpu intensive (~2ms for bracket depth=1 and the exemple file).
Also noting that Regular Expressions are bad for code simplicity.

So at this point I'll recommend using, if present: jq, node, python or the current method, to decode the json.

bhilburn commented 7 years ago

Thanks for the expert opinion, @V1rgul!

Based on this, what, if any, changes would you recommend to our existing segment code?

V1rgul commented 7 years ago

I think we should use jq.
Using nodejs as a fallback isn't an option:

time (repeat   10 { node -e 'console.log(require(process.argv[1]).name);' ./package.json >> /dev/null })
0,45s user 0,03s system 96% cpu 0,495 total
time (repeat   10 { jq '.name' package.json > /dev/null })  
0,01s user 0,01s system 51% cpu 0,039 total
time (repeat 1000 { jq '.name' package.json > /dev/null })  
0,03s user 0,60s system 36% cpu 1,731 total

So the question stands with, do we still use the current method as a fallback ?

fracmak commented 7 years ago

This is very much an edge case, this is the first repo out of hundreds that I've seen done this way. It might not be with fixing if the performance is way worse. I agree node.js is too slow

bhilburn commented 7 years ago

Thanks for the testing, @V1rgul. I agree with you @fracmak that `node.js' is clearly too slow.

I'm always very hesitant to add additional dependencies / requirements for a working P9K installation, but it would be good to somehow inform users that installing jq will improve the performance of this segment.

Here's my suggestion: When P9K initializes, use the segment_in_use utility function to test for whether or not this segment is on. If it is, print a one-time warning that recommends the use of jq.

Thoughts?

fracmak commented 7 years ago

I ran some tests locally and jq is definitely faster than the current awk/grep combo

time (repeat 1000 { jq '.name' package.json > /dev/null })                                                                                     
3.31s user 1.21s system 77% cpu 5.820 total
time (repeat 1000 { cat "./package.json" 2> /dev/null | grep -m 1 "\"name\"" | awk -F ':' '{print $2}' | awk -F '"' '{print $2}' }) > /dev/null
4.86s user 4.15s system 190% cpu 4.729 total
dritter commented 7 years ago

Just a quick idea: Why not trying more than one method to extract the name? I would do it like that (pseudo code):

local pkgFile="package.json"
local packageName=$(jq '.name' ${pkgFile} 2> /dev/null || node -e 'console.log(require(process.argv[1]).name);' ./${pkgFile} 2>/dev/null || cat "./${pkgFile}" 2> /dev/null | grep -m 1 "\"name\"" | awk -F ':' '{print $2}' | awk -F '"' '{print $2}' 2>/dev/null)

It would try the jq first, then fail gracefully, try node, and at last do it with grep and awk. That way jq won't be a hard dependency.

@fracmak Awesome testing! 👍

bhilburn commented 7 years ago

Actually, my understanding is that @dritter and @V1rgul are suggesting the same thing. @V1rgul's point, I think, was that by failing gracefully, it enables users to not have to install jq, which could lead to them seeing improper truncation.

I do want to fail gracefully because I don't want to add a dependency, but I also want to make users aware that installing jq will give them a better segment.

bhilburn commented 7 years ago

@fracmak - I'd like to move ahead with getting this merged. Let's document that jq is the proper solution in the README, but fall back to the current regex to avoid mandating additional dependencies. That does mean it's possible users will end up with invalid truncation, but I think that's the right compromise.

@fracmak @V1rgul - What needs to happen on this branch to finalize it for merge?

V1rgul commented 7 years ago

The exemple dritter commented should be ok, it just needs to be integrated into the source

dritter commented 7 years ago

Hi all!

I created PR #411 for this. Could you confirm that the fix works as expected? That would be nice. 👍

bhilburn commented 7 years ago

Whoa, awesome work, @dritter!

@fracmak @V1rgul - Can you guys give @dritter's branch a try and see if it works for you?

bhilburn commented 7 years ago

Merged #411 into next.