Skip to main content

Deprecating the bash rprompt

ยท 4 min read

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:

  1. 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
  2. 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
  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 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.