-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs(blog): bash rprompt deprecation statement
- Loading branch information
1 parent
cd9c7f5
commit 2334f41
Showing
1 changed file
with
82 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
--- | ||
title: "Deprecating the bash rprompt" | ||
description: "Deprecating the bash rprompt" | ||
slug: deprecating-bash-rprompt | ||
authors: | ||
- name: Jan De Dobbeleer | ||
title: Maintainer | ||
url: https://github.com/jandedobbeleer | ||
image_url: https://avatars.githubusercontent.com/u/2492783?v=4 | ||
tags: [breaking, ohmyposh] | ||
hide_table_of_contents: false | ||
--- | ||
|
||
After careful consideration, it was decided to remove support for the [`rprompt`][rprompt] in bash. If you are | ||
interested in the reasons behind this decision, please read on. | ||
|
||
<!--truncate--> | ||
## Context | ||
|
||
[`rprompt`][rprompt] is a feature that allows you to display a prompt at the right side of the terminal, on | ||
the same line as your cursor. This feature is available natively on a lot of shells, but not on bash. | ||
To work around this limitation, Oh My Posh has a **custom implementation** we use for both bash and PowerShell. | ||
|
||
## History | ||
|
||
### First implementation | ||
|
||
There were two evolutions of bash' custom [`rprompt`][rprompt] in Oh My Posh. The first one printed the [`rprompt`][rprompt] | ||
together with the primany prompt in the `PS1` variable, so we only need one CLI call to visualize the prompt. | ||
|
||
The challenge is that, as the [`rprompt`][rprompt] is printed together with the primary prompt, we need to make sure | ||
bash' readline can interprete the prompt correctly. In bash, every character that isn't a printable character, | ||
like color codes, needs to be wrapped in `\[` and `\]`. This is necessary to make sure bash can **calculate the length** | ||
of the prompt and ultimately **position the cursor** correctly. | ||
|
||
It turned out that for [`rprompt`][rprompt], this _needed to be done differently_. The [`rprompt`][rprompt] is printed after what | ||
bash interpretes as the end of the prompt. We found out that we need to wrap the entire [`rprompt`][rprompt] in `\[` and `\]`, | ||
and not escape individual non-printable characters. | ||
|
||
We did that for a while, but apparently this approach was **not very robust**. It was easy to break readline's | ||
cursor position calculation, and it was hard to debug. The behaviour of this was also different cross platform, | ||
so we had to go back to the drawing board. | ||
|
||
### Second implementation | ||
|
||
The second implementation of the [`rprompt`][rprompt] was a lot more robust. We decided to print the [`rprompt`][rprompt] in a separate | ||
CLI call, so we could control the output more easily. It leveraged the use of the `PROMPT_COMMAND` variable in bash, which | ||
is a hook that is executed before the prompt is printed. We would first print the [`rprompt`][rprompt] in the `PROMPT_COMMAND`, | ||
and then set the primary prompt in the `PS1` variable so bash would not bother about the [`rprompt`][rprompt] being there. | ||
|
||
This approach was a lot **cleaner from an achitectural point of view**, but it had some downsides. | ||
The biggest downside was needing two CLI calls to print the prompt, which is not a big issue, | ||
but it was a bit slower than the first implementation. | ||
|
||
Additionally, as we print before `PS1` is evaluated, it introduced the following issues: | ||
|
||
1. when the output of the previous command didn't end with a newline, the [`rprompt`][rprompt] would be printed on the same line | ||
as the output of the previous command | ||
2. when the prompt was at the bottom of the terminal buffer, the [`rprompt`][rprompt] would be printed on the same line as the | ||
prompt, which would break the prompt | ||
3. depending on the platform, it would still break command history navigation | ||
4. it required different logic for multiline prompts as we print before `PS1` and need to reposition the cursor correctly | ||
|
||
Of these issues, **only bullet 4 could be fixed**. Everything else was out of our control. | ||
|
||
## Conclusion | ||
|
||
Oh My Posh is a tool that needs to be easy to use, maintain and be 100% reliable. One of the core principles of Oh My Posh is that it should | ||
**never break the shell**. The [`rprompt`][rprompt] feature in bash has never been reliable enough, and it was _hard to debug_ when it broke. | ||
I have spent countless hours debugging issues with the [`rprompt`][rprompt] in bash, but it's **time to move on**. If you | ||
want to use the [`rprompt`][rprompt] feature, I would recommend using a shell that supports it natively, like [nushell], [zsh] or [fish]. | ||
|
||
## What about Powershell? | ||
|
||
The [`rprompt`][rprompt] feature in PowerShell is **100% reliable**, even if it's not natively supported. PowerShell doesn't | ||
have the same challenges calculating the actual prompt width like bash, there's _no need to escape anything_. | ||
We can use the first implementation mentioned above, and it works like a charm. | ||
|
||
[rprompt]: /docs/configuration/block#type | ||
[nushell]: https://www.nushell.sh/ | ||
[zsh]: https://www.zsh.org/ | ||
[fish]: https://fishshell.com/ |