zsh prompt wrapping to a newline after adding buildstatus

安稳与你 提交于 2019-12-25 06:19:06

问题


I'm attempting to add my Buildkite (ci build server) project status to the zsh prompt! I've written a ruby script that pulls the status and puts it into a colon separated file in the following format:

# .buildkite_status
project1: √
project2: x

The √ and x are ansi colour coded.

And I have a prompt that works fine until I add my $ci_build variable/function to the RPROMPT!

At the moment my prompt looks like;

~/.dotfiles »                                         ± master*:3cce1cb

and after the change I want

~/.dotfiles »                                         ± master*:3cce1cb √

The problem I'm facing is the introduction of the ci_build is now wrapping my prompt. after a week of reading docs and tweaking, I'm out of suggestions. I really would love this to work, but would prefer it working correctly.

Here is an image of the problem: https://www.dropbox.com/s/ufj82ipd7bm0o30/Screenshot%202015-06-11%2016.52.11.png?dl=0

zsh.rc

build_status() {
  current_directory=$(basename $PWD)
  var=$(cat ~/.buildkite_status | grep \^$current_directory: | awk -F':' '{print $2}')
  echo -n $var | tr '\n' ' '
}

local git_formats="%{${fg_bold[yellow]}%}± %b%c%u:%.7i%{${reset_color}%}"
zstyle ':vcs_info:git*' enable git
zstyle ':vcs_info:git*' check-for-changes true
zstyle ':vcs_info:git*' get-revision true
zstyle ':vcs_info:git*' stagedstr "+"
zstyle ':vcs_info:git*' unstagedstr "*"
zstyle ':vcs_info:git*' formats "$git_formats"
zstyle ':vcs_info:git*' actionformats "%a $git_formats"

precmd() {
  vcs_info
  build_status
}

zle-keymap-select() { zle reset-prompt; }
zle -N zle-keymap-select

VI_MODE_INDICATOR="%{$fg_bold[red]%}<%{$fg[red]%}<<%{$reset_color%}"
vi_mode_prompt_info() {
  echo "${${KEYMAP/vicmd/$VI_MODE_INDICATOR}/(main|viins)/}"
}

local cwd='%{${fg_bold[green]}%}$(prompt_pwd)%{${reset_color}%}'
local usr='%{${fg[yellow]}%}$(user_hostname)%{${reset_color}%} '
local char='%(?,%F{cyan}»,%F{red}»)%f '
local git='${vcs_info_msg_0_}$(git_stash) '
local git_author='$(git author > /dev/null || echo "$(git author) ")'
local vi_mode='$(which vi_mode_prompt_info &> /dev/null && vi_mode_prompt_info) '
local bg_job='%{${fg_bold[black]}%}$(prompt_bg_job)%{${reset_color}%} '
local ci_build='%{$(build_status)%} '

PROMPT=$cwd$usr$char
RPROMPT=$vi_mode$bg_job$git_author$git$ci_build

回答1:


The issue is caused by the way you include the output of build_status:

local ci_build='%{$(build_status)%} '

According to the zsh manual

%{...%}

Include a string as a literal escape sequence. The string within the braces should not change the cursor position

zsh assumes that $ci_build contains only escape sequences and prints out to a length of 0 characters, while it also contains the character showing the status and a space, thus being actually 2 characters longer.

As there is no actual right-alignment in the terminal zsh calculates the position of the right prompt from its perceived length. As it is 2 characters longer then calculated the right prompt wraps over the end of line, placing the cursor on the next line.

The quick fix for this problem is to use %G inside %{...%} to tell zsh that there are characters that will be output. %G stands for one character, for more characters you can either use the appropriate amount of %G or put the matching number between % and G:

local ci_build='%{$(build_status)%2G} '

The cleaner fix would be to keep the ANSI codes (and possibly the special characters you are using) out of the status file and just use zsh features for that.



来源:https://stackoverflow.com/questions/30749223/zsh-prompt-wrapping-to-a-newline-after-adding-buildstatus

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!