Removing the useless space at the end of the right prompt of zsh ($RPROMPT)

8,113

Solution 1

TL;DR

All you need to do is put this in your ~/.zshrc (or in the same file as your prompt theme):

ZLE_RPROMPT_INDENT=0

Details

In versions of ZSH leading up to 5.0.2 a value in ZSH's C source code called rprompt_off (which set the right-margin offset) was hard-coded to 1.

But in the 5.0.5 release the developers added the ability to override this default value by setting the ZLE_RPROMPT_INDENT environment variable.

The rationale for this "indent" is because some older terminals would start scrolling if the last cell of the display had a character in it.

For versions of ZSH prior to 5.0.5

If you're on an older version of ZSH and can't update, you can still get rid of that space by doing both of the following:

  1. Trick ZSH into thinking your RPROMPT is a character shorter than it actually is using the standard invisible sequence wrapper: %{...%}
  2. Then sending a cursor-back escape sequence using terminfo: %{terminfo[cub1]}

Check out the FAQ and this message on the mailing list for more info.

Solution 2

I have sent a bug report to the zsh maintainers, but it seems this behavior is by design. This issue however annoyed me so much that I decided to patch and compile zsh myself as a temporary fix. If you're on OS X and use Homebrew (you should), then you can install zsh including my patch by running:

brew install https://gist.github.com/padde/7963205/raw/eaedcc557859a40db87282fc39256fccd52d0aad/zsh.rb

you will likely want to add /usr/local/bin/zsh to /etc/shells and chsh -s /usr/local/bin/zsh afterwards. Lastly, here's the raw diff for anyone who's interested:

diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c
index 17b78ce..f136178 100644
--- a/Src/Zle/zle_refresh.c
+++ b/Src/Zle/zle_refresh.c
@@ -1576,7 +1576,7 @@ zrefresh(void)
    else
        put_rpmpt = rprompth == 1 && rpromptbuf[0] &&
        !strchr(rpromptbuf, '\t') &&
-       (int)ZR_strlen(nbuf[0]) + rpromptw < winw - 1;
+       (int)ZR_strlen(nbuf[0]) + rpromptw < winw;
     } else {
 /* insert >.... on first line if there is more text before start of screen */
    ZR_memset(nbuf[0], zr_sp, lpromptw);
@@ -1631,9 +1631,9 @@ zrefresh(void)
    if (put_rpmpt && !iln && !oput_rpmpt) {
        int attrchange;

-       moveto(0, winw - 1 - rpromptw);
+       moveto(0, winw - rpromptw);
        zputs(rpromptbuf, shout);
-       vcs = winw - 1;
+       vcs = winw;
    /* reset character attributes to that set by the main prompt */
        txtchange = pmpt_attr;
        /*

Solution 3

I think the white space to the right is hard-coded. But you can trick zsh with the following setting:

RPROMPT="%{*%}"

which in principle tells zsh that the star occupies no characters; from man zshmisc:

%{...%} Include a string as a literal escape sequence. The string within the braces should not change the cursor position. (...)

The drawback is, that you "shift" the blank to the end of PROMPT:

|PROMPT="#"                                                                  |
|RPROMPT="%{*%}"                                                             |
|# ■                                                                        *|

The | symbols denote the terminal edges, ■ the cursor.


Another idea would be to increase COLUMNS by 1:

COLUMNS=$((COLUMNS + 1))

But one has to think of a way how to do this only for the prompt rendering, but not for the commands. And this will swallow the last character on each line on a multi-line command line.

Share:
8,113

Related videos on Youtube

Frozax
Author by

Frozax

Updated on September 18, 2022

Comments

  • Frozax
    Frozax over 1 year

    In zsh, there is always a space character at the right of my right prompt. I tried with a very simple .zshrc such as:

    PROMPT="#"
    RPROMPT="*"
    

    There is a always a space after the * on the right of the screen.

    Here is a screenshot showing the issue (I selected the space on one of the lines). http://i.imgur.com/cnfa2eJ.png

    Thanks.

  • Frozax
    Frozax over 10 years
    Thanks. I tried to play with the %{...%} trick, dealing with my time and git status displayed on the right. I don't mind the extra space on the PROMPT because I do have one usually. However, there is one big drawback with this solution: when I activate auto-completion with TAB, the extra space is removed and it's doing weird things :)
  • Rob Kennedy
    Rob Kennedy about 8 years
    This also seems to place the input cursor one character to the left of where it would normally be. Using the prompts in this question, for example, the cursor is placed on the hash mark, rather than immediately to its right. (For me, setting the offset to a value less than zero makes the prompts and cursor appear in the correct places. Observed with zsh 5.0.8 and 5.2.)
  • Kim Frost Nielsen
    Kim Frost Nielsen about 8 years
    Works for me in 5.2.
  • roboslone
    roboslone almost 8 years
    It kinda worked for me in 5.2, but now I have issues with PROMPT: last character in PROMPT disappeared and toggling autocompletion fills that last character with first character of current input. For example %git<Tab> transforms to %ggit
  • Kim Frost Nielsen
    Kim Frost Nielsen almost 8 years
    You don't need to use the tricks for newer versions of ZSH.
  • Sparhawk
    Sparhawk over 7 years
    FWIW ZLE_RPROMPT_INDENT=0 works fine for me in zsh 5.2, but only in some terminal emulators. For example vte3 fails, as per @roboslone's comment. I've tested terminator-gtk3-bzr and gnome-terminal in Arch Linux.
  • Marc Liyanage
    Marc Liyanage about 5 years
    After setting ZLE_RPROMPT_INDENT=0 I noticed the same drawing glitch issues with the left-side prompt that some others mention above. However, almost everything works as expected if I use -1 instead of 0, i.e. ZLE_RPROMPT_INDENT=-1. I saw that tip at github.com/bhilburn/powerlevel9k/issues/…. Almost, because with -1 it never uses the bottom line of a terminal window on macOS.