Deprecating the bash rprompt
After careful consideration, it was decided to remove support for the rprompt
in bash. If you are
interested in the reasons behind this decision, please read on.
Contextโ
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
in Oh My Posh. The first one printed the 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
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
, this needed to be done differently. The rprompt
is printed after what
bash interpretes as the end of the prompt. We found out that we need to wrap the entire 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
was a lot more robust. We decided to print the 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
in the PROMPT_COMMAND
,
and then set the primary prompt in the PS1
variable so bash would not bother about the rprompt
being there.
This approach was a lot cleaner from an achitectural point of view, but it came with its own challenges. The most obvious one is needing two CLI calls to print the prompt, which made rendering a bit slower than the first implementation.
Additionally, as we print before PS1
is evaluated, we noticed the following issues along the way:
- when the output of the previous command didn't end with a newline, the
rprompt
would be printed on the same line as the output of the previous command - when the prompt was at the bottom of the terminal buffer, the
rprompt
would be printed on the same line as the prompt, which would break the prompt - depending on the platform, it would still break command history navigation
- 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 outside 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
feature in bash has never been reliable enough, and it was hard to debug when it broke.
I spent countless hours debugging issues with the rprompt
in bash, but it's time to move on. If you
want to use the rprompt
feature, I would recommend using a shell that supports it natively, like nushell, zsh or fish.
What about Powershell?โ
The 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.