minimal RTL support for single lines
version=0.1.0-main+4ac9610b
right now this is how بسم الله الرحمن الرحيم
will look in ghostty
and like this in konsole
there are multiple issues first the characters shaping is wrong in Arabic and Persian each glyph changes shape depending on the glyph behind it and after it for example:
ignore the "e)" it is there just to make the Arabic text left aligned
e) ي + ز + ن the first letter is "ي" and the last is "ن" should be shaped like this e) يـ + ـز + ن not like this e) ( ي + ز + ن ) or (ي + ز + ـن)
the second issue is glyph order in each word
e) علي (correct)
even if the first issue was fixed the text will look like this
e) ﻲﻠﻋ (wrong)
the third issue is word ordering, I don't think there is one correct answer there are two options
the first is to not change anything
firstWord secondWord
or make it like konsole
secondWord firstWord
I'll say up front I'm not very familiar with RTL languages on computers. I have read the full RTL/Bidi terminal spec here and I don't currently plan on supporting that in the near term since it requires a very significant amount of effort that I'm not ready to put forward. One day, I'd like to support this.
If what you're suggesting can be resolved in a renderer/shaping-only way then I think we can at least get partial RTL support, so I'll keep this open for that. 😄 More research necessary.
Thank you for the example text and screenshots, this will help significantly.
Hello. I meant to open an issue regarding this but found this one. I am using the 1.0 Dec26 version of Ghostty. I am on MacOS.
The shaping seems to work fine. All the letters are shaped properly. Problem is they are the wrong order. If I were to guess, they are probably passed to the shaper in the opposite order of what they should be. I don't know what shaper you're using, but HarfBuzz and rustybuzz want the text in the logical order and they give you the rendering order from left to right.
minimal example
Here is how it looks (correctly) in Terminal.app
same on fedora 41
kitty(right) ordering the letters correctly:
Until the RTL Support added in the future I encourage you to use bicon with ghostty, or use wezterm "it supports RTL very will
Could I suggest a slight tweak to the wording of the features page related to this? That page currently says:
Certain languages like Arabic and Hebrew are also rendered correctly (LTR only).
which is a little like saying "English text renders correctly (backwards only)." I think it would be clearer to say something like:
While only left-to-right text is supported, characters from RTL scripts including Arabic and Hebrew are correctly clustered and rendered.
@mjec Happy to make that change, would you be open to PR-ing it to the website repo?
Could I suggest a slight tweak to the wording of the features page related to this? That page currently says:
Certain languages like Arabic and Hebrew are also rendered correctly (LTR only).
which is a little like saying "English text renders correctly (backwards only)." I think it would be clearer to say something like:
While only left-to-right text is supported, characters from RTL scripts including Arabic and Hebrew are correctly clustered and rendered.
Ghostty does not render characters in RTL scripts correctly, though. They are rendered backwards. Would you say olleh is a correct clustering and rendering of hello? It would be much clearer to say that Ghostty does not support RTL scripts (like Arabic and Hebrew).
Would you say
ollehis a correct clustering and rendering ofhello?
I would say that each grapheme is correctly clustered and rendered, even though the text direction is wrong. My understanding is individual grapheme clusters in RTL scripts are correctly rendered, though RTL text direction isn't.
If that's incorrect, let me know; I'm certainly not an expert. But if that's correct and you think the proposed text doesn't accurately capture that idea, I'd be very open to suggested changes.
(Ideally this conversation should probably happen on the website repo, but I'm yet to open the promised PR.)
?hsilgnE troppus yttsohG soeD
The only good RTL terminal I’ve used so far is Konsole.
I hope to see this feature added to Ghostty soon.
I was misled by the documentation claiming it supports Arabic, but it doesn’t handle RTL properly. Instead, it reverses the text—for example, Hello World becomes dlroW olleH.
Maybe libraqm's minimal implementation can be helpful on how to integrate a bidi library with shaper https://github.com/HOST-Oman/libraqm
macOS side, ghostty vs macOS terminal vs iterm2, the second one is correct, the text is "ابراهیم"
Hello @mitchellh , I have been looking through the code recently and I believe I know where the fix for this can be: /src/font/shaper/run.zig.
As far as I understand the code, and I am not familiar with Zig so I might be mistaken, this is the function that is responsible for cutting text into runs before moving it to shaping. Shaping engines (I know harfbuzz does) require for their API calls to have each run has 1 direction and 1 direction only.
The solution for that is to run the Unicode Bidirectional Algorithm to segment the line into runs before sending them to shaper. This is pretty much what the linked file does.
~~Searching for a bit, I found the zg library which seems to handle all text needs~~ (edit: apparently it does not have the UnicodeBidi algorithm). There is a popular C library Sheenbidi. (edit: it is also implemented in libicu).
Ideally I would go and ty and implement this myself, but 1. I am not clear on what the policy for dependencies is in this project. Implementing the algorithm separately (w/o a library) is probably pointless and error prone; and 2. I am not familiar with Zig at all, so before doing anything on the codebase I need to learn Zig first.
I do plan on hacking on this regardless (at some point). But I would like to understand, before I begin, the dependency story. Can I just import the aforementioned C library and work on that?
Searching for a bit, I found the
zglibrary which seems to handle all text needs.
Luckily for you, #5694.
Searching for a bit, I found the
zglibrary which seems to handle all text needs.Luckily for you, #5694.
Unfortunately (searching the codebase) I cannot tell if it has the UnicodeBidi algo. The Readme does not mention it at all.
If zg doesn't have the Unicode bidirectional data necessary for shaping RTL languages I think that your time would be well spent contributing that to zg first, rather than trying to introduce another C library into the project.
If
zgdoesn't have the Unicode bidirectional data necessary for shaping RTL languages I think that your time would be well spent contributing that tozgfirst, rather than trying to introduce another C library into the project.
I’m not interested in reimplementing a complex and error prone algorithm. Especially if multiple libraries already exist.
Hebrew diacritics seem to be even more broken than just the reveresd text:
It should render like this:
שלום עולם
א בְּרֵאשִׁית, בָּרָא אֱלֹהִים, אֵת הַשָּׁמַיִם, וְאֵת הָאָרֶץ. ב וְהָאָרֶץ, הָיְתָה תֹהוּ וָבֹהוּ, וְחֹשֶׁךְ, עַל-פְּנֵי תְהוֹם; וְרוּחַ אֱלֹהִים, מְרַחֶפֶת עַל-פְּנֵי הַמָּיִם. ג וַיֹּאמֶר אֱלֹהִים, יְהִי אוֹר; וַיְהִי-אוֹר. ד וַיַּרְא אֱלֹהִים אֶת-הָאוֹר, כִּי-טוֹב; וַיַּבְדֵּל אֱלֹהִים, בֵּין הָאוֹר וּבֵין הַחֹשֶׁךְ. ה וַיִּקְרָא אֱלֹהִים לָאוֹר יוֹם, וְלַחֹשֶׁךְ קָרָא לָיְלָה; וַיְהִי-עֶרֶב וַיְהִי-בֹקֶר, יוֹם אֶחָד.
Additionally, Ghostty seems to have defaulted to serif sans instead of a monospaced font that supports Hebrew.
The only good RTL terminal I’ve used so far is Konsole.
Gnome terminal seems to support Hebrew properly; Idk if diacritics and Arabic ligatures work tho, checked neither.
Has there been any progress on this? It would be fantastic if a non-trash terminal emulator (i.e. not Konsole) out there finally develops a way to get Arabic working on Linux for once. @Majoramari @asibahi @ebraminio
Has there been any progress on this? It would be fantastic if a non-trash terminal emulator (i.e. not Konsole) out there finally develops a way to get Arabic working on Linux for once. @Majoramari @asibahi @ebraminio
Konsole is the best for RTL, there is Cosmic-term but it is still Alpha
Hebrew diacritics seem to be even more broken than just the reveresd text:
It should render like this:
שלום עולם א בְּרֵאשִׁית, בָּרָא אֱלֹהִים, אֵת הַשָּׁמַיִם, וְאֵת הָאָרֶץ. ב וְהָאָרֶץ, הָיְתָה תֹהוּ וָבֹהוּ, וְחֹשֶׁךְ, עַל-פְּנֵי תְהוֹם; וְרוּחַ אֱלֹהִים, מְרַחֶפֶת עַל-פְּנֵי הַמָּיִם. ג וַיֹּאמֶר אֱלֹהִים, יְהִי אוֹר; וַיְהִי-אוֹר. ד וַיַּרְא אֱלֹהִים אֶת-הָאוֹר, כִּי-טוֹב; וַיַּבְדֵּל אֱלֹהִים, בֵּין הָאוֹר וּבֵין הַחֹשֶׁךְ. ה וַיִּקְרָא אֱלֹהִים לָאוֹר יוֹם, וְלַחֹשֶׁךְ קָרָא לָיְלָה; וַיְהִי-עֶרֶב וַיְהִי-בֹקֶר, יוֹם אֶחָד.
Additionally, Ghostty seems to have defaulted to serif sans instead of a monospaced font that supports Hebrew.
The only good RTL terminal I’ve used so far is Konsole.
Gnome terminal seems to support Hebrew properly; Idk if diacritics and Arabic ligatures work tho, checked neither.
arabic suffer from the same issue, it is nicely rendered though, but without any rtl
however the Arabic لا is the only that isn't been rendered properly and is cut from the rest, konsole have a workaround this by removing the لا ligatures
If
zgdoesn't have the Unicode bidirectional data necessary for shaping RTL languages I think that your time would be well spent contributing that tozgfirst, rather than trying to introduce another C library into the project.
Since then I changed my mind and ported the bidi algorithm to Zig. The library itself it data source agnostic (can use the user's unicode data source.) The Zig port passes all compliance tests but I have not added benchmarks yet.
I noticed some Hebrew letters with diacritics render heavier than others and with completely different spacing. Not sure exactly why, but it's quite annoying.
I've had to revert to konsole, but would love to come back to ghostty.
I don't want to overstep on the maintainers here but this looks like a font fallback issue. You might want to specify a Hebrew font in the config.
You're right @asibahi ! Ghostty used 3 different fonts rendering that string. The way I solved it was:
- Remove
binding="strong"from~/.config/fontconfig/fonts.conf - Add
font-family = "Noto Sans Hebrew"(NOTfont-family = "Noto Sans")
Once I found ghostty +show-face --string="" it was a breeze. Wish these things worked out of the box.
Re (1), no one can figure out why binding="strong" breaks things for Ghostty and Ghostty only (xref https://github.com/ghostty-org/ghostty/discussions/3015#discussioncomment-12102460).
Can't some grant be secured from the rich Gulf states? UAE invests so heavily in new technology.
@mitchellh Perhaps if you try to reach out, they'll pay for adding this feature. I have no idea how to do that though. Perhaps through a collaboration with someone at MBZUAI.
Until the RTL Support added in the future I encourage you to use bicon with ghostty, or use wezterm "it supports RTL very will
Can you use bicon with ARM macOS? The last time I checked it didn't work.
a) Please do not ping maintainers.
b) Ghostty is an all-volunteer project and nobody here is interested in financial gains. Mitchell doesn't particularly need oil money only made possible with indentured labor, either. Perhaps instead of capital, lend us some hands instead.