add "mess when resizing" to troubleshooting
This commit is contained in:
parent
cea51ee866
commit
0b9829d409
128
README.md
128
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)
|
||||
|
|
Loading…
Reference in New Issue