aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorromkatv <roman.perepelitsa@gmail.com>2020-02-01 19:37:04 +0300
committerromkatv <roman.perepelitsa@gmail.com>2020-02-01 19:37:04 +0300
commit0b9829d409cba321f77729e1010c5b0480529cfa (patch)
treea6e37e900d4deed9b404a346913582b7f335fbc0
parentcea51ee86638230dc68a967c6899649ab162e8e9 (diff)
add "mess when resizing" to troubleshooting
-rw-r--r--README.md128
1 files changed, 128 insertions, 0 deletions
diff --git a/README.md b/README.md
index 7dbff5b2..73e9d4dc 100644
--- a/README.md
+++ b/README.md
@@ -1198,6 +1198,133 @@ There are several ways to fix this.
The parameter you are looking for is called `POWERLEVEL9K_DIR_BACKGROUND`. You can find it in
in `~/.p10k.zsh`. Uncomment it if it's commented out and try different values.
+### Horrific mess when resizing terminal window
+
+When you resize terminal window horizontally back and forth a few times, you might see this ugly
+picture.
+
+![Powerlevel10k Resizing Mess](
+ https://raw.githubusercontent.com/romkatv/powerlevel10k-media/master/resizing-mess.png)
+
+tl;dr: This is a bug in Zsh that isn't specific to Powerlevel10k. See [mitigation](#mitigation).
+
+#### Zsh bug
+
+This issue is caused by a bug in Zsh that gets triggered the vertical distance between the start of
+the current prompt and the cursor (henceforth `VD`) changes when the terminal window is resized.
+This bug is not specific to Powerlevel10k.
+
+When a terminal window gets shrunk horizontally, there are two ways for a terminal to handle long
+lines that no longer fit: *reflow* or *truncate*.
+
+Terminal content before shrinking:
+
+![Terminal Content Before Shrinking](
+ https://raw.githubusercontent.com/romkatv/powerlevel10k-media/master/resize-original.png)
+
+Terminal reflows text when shrinking:
+
+![Terminal Reflows Text When Shrinking](
+ https://raw.githubusercontent.com/romkatv/powerlevel10k-media/master/resize-reflow.png)
+
+Terminal truncates text when shrinking:
+
+![Terminal Truncates Text When Shrinking](
+ https://raw.githubusercontent.com/romkatv/powerlevel10k-media/master/resize-truncate.png)
+
+Reflowing strategy can change the hight of terminal content. If such content happens to be between
+the start of the current prompt and the cursor, Zsh will print prompt on the wrong line. Truncation
+strategy never changes the hight of terminal content, so it doesn't trigger this bug in Zsh.
+
+Let's see how the bug plays out in slow motion. We'll start by launching `zsh -df` and pasting
+the following code:
+
+```zsh
+function pause() { read -s }
+functions -M pause 0
+
+reset
+print -l {1..3}
+setopt prompt_subst
+PROMPT=$'${$((pause()))+}left>${(pl.$((COLUMNS-12))..-.)}<right\n> '
+```
+
+When `PROMPT` gets expanded, it calls `pause` to let us observe the state of the terminal. Here's
+the initial state:
+
+![Zsh Resizing Bug 1](
+ https://raw.githubusercontent.com/romkatv/powerlevel10k-media/master/resize-bug-1.png)
+
+Zsh keeps track of the cursor position relative to the start of the current prompt. In this case it
+knows that the cursor is one line below. When we shrink the terminal window, it looks like this:
+
+![Zsh Resizing Bug 2](
+ https://raw.githubusercontent.com/romkatv/powerlevel10k-media/master/resize-bug-2.png)
+
+At this point the terminal sends `SIGWINCH` to Zsh to notify it about changes in the terminal
+dimensions. Note that this signal is sent *after* the content of the terminal has been reflown.
+
+When Zsh receives `SIGWINCH`, it attempts to erase the current prompt and print it anew. It goes to
+the position where it *thinks* the current prompt is -- one line above the cursor (!) -- erases all
+terminal content that follows and prints reexpanded prompt there. However, after resizing prompt is
+no longer one line above the cursor. It's two lines above! Zsh ends up printing new prompt one line
+too low.
+
+![Zsh Resizing Bug 3](
+ https://raw.githubusercontent.com/romkatv/powerlevel10k-media/master/resize-bug-3.png)
+
+In this case we ended up with unwanted junk content because `VD` has *increased*. When you make
+terminal window wider, `VD` can also *decrease*, which would result in the new prompt being printed
+higher than intended, potentially erasing useful content in the process.
+
+Here are a few more examples where shrinking terminal window increased `VD`.
+
+Simple one-line left prompt with right prompt. No `prompt_subst`. Note that the cursor is below the
+prompt line (hit *ESC-ENTER* to get it there).
+
+![Zsh Prompt That Breaks on Terminal Shrinking 1](
+ https://raw.githubusercontent.com/romkatv/powerlevel10k-media/master/resize-breakable-1.png)
+
+Simple one-line left prompt. No `prompt_subst`, no right prompt. Here `VD` is bound to increase
+upon terminal shrinking due to the command line wrapping around.
+
+![Zsh Prompt That Breaks on Terminal Shrinking 2](
+ https://raw.githubusercontent.com/romkatv/powerlevel10k-media/master/resize-breakable-2.png)
+
+#### Zsh patch
+
+The bug described above has been fixed in [this branch](
+ https://github.com/romkatv/zsh/tree/fix-winchanged). The idea behind the fix is to use `sc` (save
+cursor) terminal capability before printing prompt and `rc` (restore cursor) to move cursor back
+to the same position when prompt needs to be refreshed.
+
+There are two alternative approaches to fixing the bug that may seem to work at fight glance but in
+fact don't:
+
+- Instead of `sc`, use `u7` terminal capability to query the current cursor position and then `cup`
+ to go back to it. This doesn't work because the absolute position of the start of the current
+ prompt changes when text gets reflown.
+- Recompute `VD` based on new terminal dimensions before attempting to refresh prompt. This doesn't
+ work because Zsh doesn't know whether terminal reflows text or truncates it. If Zsh could somehow
+ know that the terminal reflows text, this approach still wouldn't work on terminals that
+ continuously reflow text and rapid-fire `SIGWINCH` when the window is being resized. In such
+ environment real terminal dimensions go out of sync with what Zsh thinks the dimensions are.
+
+There is no ETA for the patch making its way into upstream Zsh. See [discussion](
+ https://www.zsh.org/mla/workers//2019/msg00561.html).
+
+#### Mitigation
+
+There are a few mitigation options for this issue.
+
+- Apply [the patch](#zsh-patch) and rebuild Zsh from source.
+- Disable text reflowing on window resize in terminal settings. If your terminal doesn't have this
+ setting, try a different terminal.
+- Avoid long lines between the start of prompt and cursor.
+ 1. Disable right prompt with `POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=()`.
+ 2. Disable ruler with `POWERLEVEL9K_SHOW_RULER=false`.
+ 3. Disable prompt gap with `POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_CHAR=' '`.
+
## Table of contents
- [Features](#features)
@@ -1266,3 +1393,4 @@ There are several ways to fix this.
- [Weird things happen after typing `source ~/.zshrc`](#weird-things-happen-after-typing-source-zshrc)
- [Cannot make Powerlevel10k work with my plugin manager](#cannot-make-powerlevel10k-work-with-my-plugin-manager)
- [Directory is difficult to see in prompt when using Rainbow style](#directory-is-difficult-to-see-in-prompt-when-using-rainbow-style)
+ - [Horrific mess when resizing terminal window](#horrific-mess-when-resizing-terminal-window)