From 2334f410f23970ad33c25eb589961c0fb8e0dd5f Mon Sep 17 00:00:00 2001 From: Jan De Dobbeleer Date: Mon, 22 Jul 2024 16:10:10 +0200 Subject: [PATCH] docs(blog): bash rprompt deprecation statement --- website/blog/2024-07-22-bash-rprompt.mdx | 82 ++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 website/blog/2024-07-22-bash-rprompt.mdx diff --git a/website/blog/2024-07-22-bash-rprompt.mdx b/website/blog/2024-07-22-bash-rprompt.mdx new file mode 100644 index 00000000..4dc92204 --- /dev/null +++ b/website/blog/2024-07-22-bash-rprompt.mdx @@ -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. + + +## 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/