-
Notifications
You must be signed in to change notification settings - Fork 234
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
fix: Align lines with emojis correctly #163
Conversation
Please do fix this upstream if you found any issues. At first glance I don't see a difference however? |
The key change is the use of I will provide a repository shortly showcasing the problem and why this pull request resolves the problem. |
I want to clarify that there is no bug with reflow. It is just providing a different answer to the question. Lipgloss needs to know the printable string width, not the printable rune width. Are you willing to accept a pull request to reflow to add this function? Lipgloss still needs to be updated to use it however. |
Yeah, definitely willing to accept PRs there, so we don't end up copying similar code all over the place. |
Cool, a few test cases might be nice here. |
Test case with both code and images. /~https://github.com/mikelorant/emoji-alignment Hopefully these results are consistent with other platforms and terminals. |
Unfortunately, I don't believe this is a valid solution. I'm already seeing different results with Kitty, however the core of the issue is with multi-sequence emojis such as the following. // alembic
"⚗️"
"\U00002697\U0000FE0F"
// kiss: woman, man, medium-dark skin tone, light skin tone (with zero width joiners)
"👩🏾❤️💋👨🏻"
"\U0001F469\U0001F3FE\U0000200D\U00002764\U0000FE0F\U0000200D\U0001F48B\U0000200D\U0001F468\U0001F3FB" Note that I'm providing both emoji literals and unicode sequences here, which Go will evaluate equally. |
Within Lipgloss the 12 byte emoji has some issues. I will continue looking into that issue and hopefully be able to work out what is going on. I think my patch still improves the situation even if it does not solve the problem fully. Emojis are extremely complicated, so instead of looking for the perfect solution its best to continually improve things. The good news is that the problem is not in Lipgloss. It all relates to |
Kitty has its own Open issue for kitty. Specific comment about |
👋 Hello, thanks for your work on this @mikelorant. I'm running into this exact issue without using multi-sequence emojis. Is it possible to move ahead with this fix? Failing that, is there a workaround available? |
What I would recommend for now is to simply avoid any emojis that are causing you problems. The crux of the issue here is that emoji widths must both be correctly calculated in both Go and on the terminal level, and neither side is perfect yet. Even Kitty, which is among the best renderers I've seen, doesn't render every single emoji correctly. Going further, even some desktop environments don't support newer emojis. We have some tooling in the works that should alleviate the problem a bit on the Go side, but there's not ETA yet. |
Got it, thanks for the additional context @meowgorithm.
Just a clarification on that front, almost all the emojis I tried are suffering from the same issue. |
@praagyajoshi which terminal, OS, and window manager (if relevant) are you using? As I mentioned this varies widely depending on terminal and can be affected by other OS-level factors. Also, we still need to test properly but I suspect that switching from |
I'd like to bring this issue up again based on some feedback from @rivo.
Using the rune width anywhere is something we need to be very careful about. In most cases I would expect we should only be using the string width. It is likely we will not see the full benefits unless we replace My recommendation would be to create a new issue for either |
Hey! We actually began work on switching to |
@meowgorithm Been tracking the great work on the This is why I have now turned my attention to As you are one of the project maintainers, would be great to get some guidance on where we should start. Something experimental to prove this will give us improvements. |
So I think ultimately we want to be counting and iterating over graphemes like you suggest. For example, ⚗️ is 6 bytes, 2 runes, and 1 grapheme cluster playground. I'd also, have a look at this excellent writeup on grapheme clusters in terminals by Mitchell Hashimoto. It's the best reference I've seen on this subject. |
Alignment issues occur when some lines have certain emojis in them. This is caused by incorrectly calculating the width of a string. For a string with emojis in them, it is important to understand that the string width is different to the rune width. Many functions within Lipgloss base the string length on the printable rune width which is incorrect. The correct method requires finding the string width. The reflow package has a printable rune width function. While the ANSI sequences need to be removed, we do not want the rune width as this function returns. This change adds a new function to get the printable string width. The code was taken from reflow and modified for use in Lipgloss. Since the printable rune width function in reflow works correctly, it was more reasonable to add the function to Lipgloss.
6d10502
to
b377e74
Compare
I've put up a preliminary pull request for |
Awesome. For reference that's muesli/reflow#71 (also FYI @muesli is on the Charm team). @maas, heads up re: |
Closing this pull request as this is going to be fixed with muesli/reflow#71. |
Alignment issues occur when some lines have certain emojis in them. This is caused by incorrectly calculating the width of a string.
For a string with emojis in them, it is important to understand that the string width is different to the rune width. Many functions within Lipgloss base the string length on the printable rune width which is incorrect. The correct method requires finding the string width.
The reflow package has a printable rune width function. While the ANSI sequences need to be removed, we do not want the rune width as this function returns.
This change adds a new function to get the printable string width. The code was taken from reflow and modified for use in Lipgloss. Since the printable rune width function in reflow works correctly, it was more reasonable to add the function to Lipgloss.