-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Fish calculating prompt length incorrectly with Unicode emoji (☁️ - cloud) #10461
Comments
Fish uses our widecharwidth script that parses the unicode data files to come up with a width representation. Notably this includes "EastAsianWidth.txt", which lists:
That means anything from U+2600 to U+2604 is classified as "N", which stands for "Neutral", which means they are "narrow" and occupy one cell. (tbh I don't really understand why "neutral" even exists, and TR11 is unhelpful here) It is also listed as "Emoji" in emoji-data.txt, but not as "Emoji_Presentation". That means you can use the U+FE0F emoji variation selector to change it from text presentation (narrow because EastAsianWidth.txt applies) to emoji presentation (wide). Fish will treat this combination as being two cells wide. This is also what I get when I copy your ☁️ here from the browser into my terminal - not just U+2601, but U+2601 followed by U+FE0F. This is also what I get from starship's default config (but again via a browser, it's always possible the U+FE0F was inserted there). You can see what your fish thinks the width is with string length -V ☁️ \U2601 \U2601\UFE0F This should print "2", "1" and "2" - if that cloud glyph is U+2601 U+FE0F. If it prints "1" "1" "2" the glyph is just U+2601. This seems correct to me from what I know of Unicode and TR11 specifically. It's not a great document, and it's not meant for terminals specifically, but it is the best we have and fish's interpretation seems reasonable to me. Fish's width handling isn't perfect either (notably it does not handle full grapheme clusters but only codepoint-by-codepoint with some hacks like for variation selectors), but the easy and medium difficulty cases usually work, and I would call this a medium case. Note: The names of $fish_emoji_width and $fish_ambiguous_width are perhaps too simple. They affect very specific things:
Neither applies to U+2601 because it is classified as neutral and not Emoji_Presentation. So, in summary: Terminal.app and iTerm obviously misrender the text. They show ☁️ (which I assume is U+2601 with the emoji selector) as being two cells wide but then don't use the second cell. Warp apparently ignores the emoji selector and draws U+2601 with the emoji selector as occupying one cell. I believe that is wrong and would therefore call this a bug in Warp. Note that the zsh comparison doesn't help much because zsh doesn't care about the width at all here, it just prints the prompt without repositioning. The issue comes up because fish repositions the cursor to do syntax highlighting, suggestions, right prompt handling, etc. Our guidance: Please draw U+2601 alone into one cell, and U+2601 U+FE0F into two cells. |
So, since I just tested this in 6 more terminals and 5 failed the same test (with various failure modes), here are some quotes from Unicode TRs to support our reading: From TR51:
[...]
So a character either has default emoji or text presentation. U+2601 does not have Emoji_Presentation so it defaults to text presentation.
So U+FE0F can be used to get emoji presentation for something that otherwise has text presentation.
So U+2601 U+FE0F is an emoji presentation sequence (it's also listed in the corresponding file). From TR11:
So anything that has Emoji_Presentation is "wide".
So U+2601 U+FE0F is wide.
So, since U+2601 is text presentation by default, the emoji stuff doesn't apply, so the "Neutral" from EastAsianWidth.txt applies. I think that should answer your question? |
Awesome - thank you @faho, and thanks for digging into this! Just wanted to ack these comments in the interim - I'm working through reading up on this world and understanding this more deeply 😅. I'll likely have some follow-up questions, but this is super helpful! 🙌 |
Updates:
Really appreciate your help on this @faho and I might have some follow-ups! Also, curious, which terminal succeeded when you tested this in 6 mentioned above haha? Hopefully Warp will be another one to add soon 😄 !! EDIT: for anyone wondering, I believe the terminal that handles this correctly is Kitty! But Warp is coming soon! |
Metadata
Fish version: fish, version 3.6.1
OS: macOS Sonoma 14.3.1
Terminal: tried on default Mac Terminal, iTerm 2 and Warp
Seeing what I'd classify as "incorrect" behavior across all terminals, and this is specific to fish (compared against zsh/bash).
Summary
Fish seems to be incorrectly calculating the width of "☁️" i.e. cloud Unicode character, resulting in incorrect cursor positions across terminals.
Intro
Hey folks! I'm a Warp engineer that came across this bug when debugging an issue for Warp (I've been working on better custom prompt support). This led me down a rabbit-hole of font rendering and Unicode + how fish calculates widths for characters with
wcwidth
haha 😅.Looking for some advice here and perhaps configuration levers for
fish
that I missed, when it comes to dealing with emoji widths (are there other variables I can modify here?)! Or whether this is something that can be tackled at the fish layer? Thanks!What I have tried
I tried playing around with setting
set -U fish_emoji_width X
andset -U fish_ambiguous_width X
for various combinations to try to fix this across the terminals below. These settings didn't seem to affect the terminals.I also cloned Starship locally and ran my terminals against a local instance to confirm it was specifically the ☁️ character which caused issues.
As noted below, I repro'ed this issue without Starship, using a vanilla
fish_prompt
across these terminals.Starship Repro
Specifically, Starship uses the ☁️ character in its popular
gcloud
prompt chip module. This chip is included by default in Starship. It seems likefish
is incorrectly calculating the width of the cloud Unicode character. This doesn't cause issues in bash/zsh, presumably since they don't attempt to layout text in the same manner that fish does.Interestingly, fish handles Powerline characters correctly (e.g. - image below, which is
![image](https://private-user-images.githubusercontent.com/12927474/325827809-6c3063ad-5d6e-4833-8e18-a1431cb0fa71.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjE4NjI2NTksIm5iZiI6MTcyMTg2MjM1OSwicGF0aCI6Ii8xMjkyNzQ3NC8zMjU4Mjc4MDktNmMzMDYzYWQtNWQ2ZS00ODMzLThlMTgtYTE0MzFjYjBmYTcxLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MjQlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzI0VDIzMDU1OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTEwNjlkZDJkNzY0NDFlN2UwNWQwODc5ZWEzYzQxOGJiOWJmMGM2MDEwMDY1ZjFkZjA4YjI4Y2UxYTA1OGFhYzcmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.iS_OEmBQsRPgRih60obHfQPNpoHXLjIkPRBEiQ5DtMo)
0xE0A0
).To repro - use this
starship.toml
:Behavior on default Mac terminal - note the 2 spaces between end of prompt and start of input, when we are only expecting 1 space.
![image](https://private-user-images.githubusercontent.com/12927474/325828805-f3092c8c-7682-4bc1-82c8-696e2fe7c686.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjE4NjI2NTksIm5iZiI6MTcyMTg2MjM1OSwicGF0aCI6Ii8xMjkyNzQ3NC8zMjU4Mjg4MDUtZjMwOTJjOGMtNzY4Mi00YmMxLTgyYzgtNjk2ZTJmZTdjNjg2LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MjQlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzI0VDIzMDU1OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPThjMjAwMGYxZjAzOTg4MzhkYjUyMWM0NDJjOGFlN2E1MWMyMDMxZWIxZDViZTI5MDhmYjU5OGU3MmJlZjZhYTUmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.k0EK8N_hbD7QVkOxOiap7EP2-xRf3lUMv5W9BRjxyJg)
Behavior on iTerm 2, again note the 2 spaces.
![image](https://private-user-images.githubusercontent.com/12927474/325828639-27f3ff61-cf10-458b-8c56-f3ea0592fd5b.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjE4NjI2NTksIm5iZiI6MTcyMTg2MjM1OSwicGF0aCI6Ii8xMjkyNzQ3NC8zMjU4Mjg2MzktMjdmM2ZmNjEtY2YxMC00NThiLThjNTYtZjNlYTA1OTJmZDViLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MjQlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzI0VDIzMDU1OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTdjODQ2Y2ZhYTk1ZTZiZjg1OWFlYTk4NmNjNTI3NTBhZDFhZTdjNThkNjc5ZGY1NGM0MDNiYTgxMDhhZmE4ZWUmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.42U3Y3QkMk1xsxULBqJouoHYD_T5Mh-OHEfu0CFzoK0)
Behavior I see with local Warp instance (where I'm working on better prompt support). Note that the double character is due to Warp skipping certain cursor instructions being sent in-between lprompt/rprompt or just post rprompt. However, the underlying cause here is the same as the terminals above, I believe. Using the
![image](https://private-user-images.githubusercontent.com/12927474/325828770-19d3e8d9-26a2-4454-aeaa-760834360669.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjE4NjI2NTksIm5iZiI6MTcyMTg2MjM1OSwicGF0aCI6Ii8xMjkyNzQ3NC8zMjU4Mjg3NzAtMTlkM2U4ZDktMjZhMi00NDU0LWFlYWEtNzYwODM0MzYwNjY5LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MjQlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzI0VDIzMDU1OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTM1MzA5MGMzMDMyZjY5ZGEyMDBjOTNjYTIzZmVkMGI0NTMwNTI3NTE2YWVkODZlZmQ3NDY0YzcwNGZmMGRkZjkmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.oT1tEvWE_KA6_6CIxxC4ALIz8xHVTeUjoPev0FTDK-Q)
Hack
font here.Expected behavior (zsh on iTerm 2):
![image](https://private-user-images.githubusercontent.com/12927474/325830138-31c5db18-2998-46fd-8c87-52744632b066.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjE4NjI2NTksIm5iZiI6MTcyMTg2MjM1OSwicGF0aCI6Ii8xMjkyNzQ3NC8zMjU4MzAxMzgtMzFjNWRiMTgtMjk5OC00NmZkLThjODctNTI3NDQ2MzJiMDY2LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MjQlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzI0VDIzMDU1OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTY5NjdiZDMwNGZjMDRkOTdmMDAxZjM3NTg3ZmNiZjUxODgzMjkzMGQ5YWRmZjg5MGFjNjg4NGM5NDk4M2FkOWImWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.VPH4OvBq3aqKhZgorLzemiy9CHG5N0DsgDK22COevGM)
Minimal Repro
Note that I can repro this without Starship entirely, for a minimal repro. For example:
Behavior I see in default Mac Terminal (1 is entirely overwritten, but this seems more on the Terminal-specific side. Notably, seeing an extra space after the
![image](https://private-user-images.githubusercontent.com/12927474/325828241-9f091f98-9d1d-467a-9f91-38d975be9e41.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjE4NjI2NTksIm5iZiI6MTcyMTg2MjM1OSwicGF0aCI6Ii8xMjkyNzQ3NC8zMjU4MjgyNDEtOWYwOTFmOTgtOWQxZC00NjdhLTlmOTEtMzhkOTc1YmU5ZTQxLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MjQlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzI0VDIzMDU1OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTUxYTI4MzQ5ZGYwNmU2ZThmOTk0NDBlMGQ3MDQ3NTRhZWZkZWY3N2FmNjE1ZWIxMjY1NDVlY2RhNzMzNTQ3ZmEmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.mluk_nk6ARSZ6QedIAXY6_re_tr1pS_uiYvvFcQpvP0)
0
here).Note that more clouds results in more spaces:
![image](https://private-user-images.githubusercontent.com/12927474/325834504-7b8e3f57-ce86-44d2-8ac1-e6e013b32bde.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjE4NjI2NTksIm5iZiI6MTcyMTg2MjM1OSwicGF0aCI6Ii8xMjkyNzQ3NC8zMjU4MzQ1MDQtN2I4ZTNmNTctY2U4Ni00NGQyLThhYzEtZTZlMDEzYjMyYmRlLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MjQlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzI0VDIzMDU1OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWYwYjZkMWU4ZDUzZTI1YWI4NTM1MDM5MDExNjJiMGRiZWQ0NjYzOGI1OWJmZTMxMTE2ZDdmMTgzNWIzMDI5MWImWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.ZdV81HhsBOntXVYmm198gLPT2-nr68EP2LcEYM2LdaM)
Behavior I see with iTerm 2 (same as above).
![image](https://private-user-images.githubusercontent.com/12927474/325828477-a04d2f51-ebdf-4b2a-a02b-e62eff216e8f.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjE4NjI2NTksIm5iZiI6MTcyMTg2MjM1OSwicGF0aCI6Ii8xMjkyNzQ3NC8zMjU4Mjg0NzctYTA0ZDJmNTEtZWJkZi00YjJhLWEwMmItZTYyZWZmMjE2ZThmLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MjQlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzI0VDIzMDU1OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWQ3OWFhNzBhYzkzNjZhMjMxNGViMTMxMzc4YjEwMmYxZDAzZmFiY2MxNzc5NGY2YWU0ZmUyOGE0NWU5NjM3ODImWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.rBkctz6JYF7y3sCzMX1WidRPSQgff61U7RHeGXVj8Ek)
Behavior I see with local Warp instance (extra space affects Warp's cursor position understanding here):
Expected behavior (zsh, default Mac terminal):
![image](https://private-user-images.githubusercontent.com/12927474/325830472-765706df-7dfe-4510-b939-1bb29dbf20d8.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjE4NjI2NTksIm5iZiI6MTcyMTg2MjM1OSwicGF0aCI6Ii8xMjkyNzQ3NC8zMjU4MzA0NzItNzY1NzA2ZGYtN2RmZS00NTEwLWI5MzktMWJiMjlkYmYyMGQ4LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MjQlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzI0VDIzMDU1OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTNjZDQ0OWM3NWE1MzkyMWFjZTI3OGM0Zjc1M2Q5MTI5M2VjNWMwYTM1ZmUwYzZhMDM3MTExODY5MGQ2ODI4YzkmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.3ghm9qSybGH8gvMtBVI0A8cLgaZNnobWQaK-5F3ViWc)
Conclusion
I'm happy to figure out fixing this on the Warp-side, if that makes most sense (I get the sense
fish
folks have looked at this a bit in the past, but it's a deep rabbit-hole) - but I wanted to flag this since I'm seeing, and ask for advice on how a terminal emulator should best tackle this, if it's on the terminal emulator side. Notably, in Warp, we treat this as a single cell character, rather than iTerm 2 or the default Mac terminal that treat the cloud as 2 cells wide.Related issues
Related issues I was reading through:
fish_prompt
gets wrong length calculated #4539The text was updated successfully, but these errors were encountered: