zsh-users
 help / color / mirror / code / Atom feed
From: Nikolai Weibull <now@bitwi.se>
To: Bart Schaefer <schaefer@brasslantern.com>
Cc: Zsh Users <zsh-users@zsh.org>
Subject: Re: zle reset-prompt with prompt that is COLUMNS wide eats line above prompt's first line
Date: Tue, 25 Jan 2011 14:23:47 +0100	[thread overview]
Message-ID: <AANLkTi=3XBAg_LTZDPSm5vCKytQohb6sCoekGLEPDA5e@mail.gmail.com> (raw)
In-Reply-To: <101210235748.ZM11748@torch.brasslantern.com>

[-- Attachment #1: Type: text/plain, Size: 2431 bytes --]

On Sat, Dec 11, 2010 at 08:57, Bart Schaefer <schaefer@brasslantern.com> wrote:
> On Dec 10, 11:40am, Nikolai Weibull wrote:
> }
> } Running zle reset-prompt with a prompt that is COLUMNS wide eats the
> } line above prompt's first line.  Here's a set-up to try it with:
> }
> } PS1=${(l:COLUMNS:)}$'\n'
> } bindkey '^^' reset-prompt
>
> The problem here isn't the width of the prompt, it's the newline.
> (OK, it's sort of the combination of the two, but more the latter.)
>
> } Each time you press CTRL-^ you'll be eating the line above the first
> } line of the prompt.  If you change PS1 to ${(l:COLUMNS-1)}$'\n' this
> } doesn't happen.
> }
> } Would it be possible to have prompt that is COLUMNS wide and have this
> } not happen?
>
> This is a problem with terminals and terminfo or termcap descriptions.
> Some terminals silently discard a newline when one is output at the
> right margin, others don't, and still others discard it only when it
> is output at the right margin of the very last line of the screen.
> Some terminals cause the cursor to wrap onto the next line right
> away when the right margin is reached, others leave the cursor on
> top of the last character that was output until at least one more
> character appears.
>
> Terminal description databases aren't very good at differentiating
> these cases.  ZLE decides in this case that the terminal both wraps
> the line and does not discard the newline, so it believes it needs
> to move up one line before redrawing the prompt.  Your terminal
> wraps at the margin but does discard the newline, so ZLE's internal
> idea of what the screen looks like does not match reality.
>
> You can get around this by replacing $'\n' with $'%1(l.\n.)' which
> means to emit the newline only if ZLE believes that at least one
> character has been output since the last (implicit) newline.  If
> the line is exactly $COLUMNS wide, ZLE will think that the terminal
> has wrapped and that zero characters have been output since, so it
> won't fool itself by emitting a newline that the terminal discards.
>
> On a different terminal, though, you might need to go back to $'\n'
> unconditionally.

It seems that there is some other complication.  I’ve attached my
prompt definition, if anyone wants to take a look.  I’m currently
running through screen inside PuTTY and iTerm, in which this trick
didn’t work.

[-- Attachment #2: prompt_now_setup --]
[-- Type: application/octet-stream, Size: 3087 bytes --]

prompt_now_help () {
  emulate -L zsh

  cat <<EOH
Nothing to see here.
EOH
}

integer PSCOL=-1
PSZERO='%([BSUbfksu]|[0-9]#[FK]({[^}]##}|))'

prompt_now_precmd () {
  emulate -L zsh
  setopt extendedglob

  psvar[8]=$?
  (( psvar[8] )) || psvar[8]=

  (( ${+functions[vcs_info]} )) && vcs_info

  prompt_now_adjust_width || return

  local -A cs
  prompt_now_chars

  local host=
  [[ -n $SSH_CONNECTION ]] && host=' %m'
  local -ah ps1
  ps1=(
    '%249K'
    "%$COLUMNS<$cs[…]<"
    '%~'
    '%8(V. [%9F%8v%f].)'
    \$vcs_info_msg_0_
    '%9v'
    $host
    '%<<'
    '%k'
    $'\n'
  )
  PS1=${(j::)ps1}

  local listprompt='More%R page: %p'
  integer fill
  (( fill = COLUMNS - ${#${${listprompt//\%R}//\%p/Top}} - 2 ))
  zstyle ':completion:*:default' list-prompt \
    "%K{white}${listprompt%\%R*}${(l:fill:)}${listprompt##*%R}%k"
}

prompt_now_winch () {
  prompt_now_adjust_width && zle && zle reset-prompt
}

prompt_now_adjust_width () {
  emulate -L zsh
  setopt extendedglob

  local saved_vcs_info_msg_0_=$vcs_info_msg_0_
  integer width

  psvar[9]=""
  vcs_info_msg_0_=${vcs_info_msg_0_//$~PSZERO}
  (( width = COLUMNS - ${#${(f)${(%%)${PS1//$~PSZERO}}}[1]} ))
  vcs_info_msg_0_=$saved_vcs_info_msg_0_
  psvar[9]=${(l:width:)}

  (( COLUMNS == PSCOL )) && return 1
  (( PSCOL = COLUMNS ))
}

prompt_now_chars () {
  case $TERM in
    (xterm-256color|screen-256color) cs=('…' '…' '“' '“' '”' '”') ;;
    (*)                              cs=('…' '...' '“' '"' '”' '"') ;;
  esac
}

prompt_now_setup () {
  emulate -L zsh
  setopt extendedglob nolocaltraps
  prompt_opts=(cr percent subst)

  zstyle ':vcs_info:*' stagedstr '%F{green}+'
  zstyle ':vcs_info:*' unstagedstr '%F{red}!'
  zstyle ':vcs_info:*' formats ' [%b%c%u%f]'
  zstyle ':vcs_info:*' actionformats ' [%a: %b%c%u%f]'

  prompt_now_teardown
  prompt_now_precmd

  local -A cs
  prompt_now_chars

  PS2='${(l|$((2 * ${(w)#${(%%):-%_}}))|)}'
  PS3='Your selection: '
  PS4='%F{yellow}+%F{blue}%N%f:%i: '

  SPROMPT="zsh: correct $cs[“]%9F%R%f$cs[”] to $cs[“]%10F%r%f$cs[”]? "

  TIMEFMT=%J$'\n''real: %*E user: %*U system: %*S (%P)'

  WATCHFMT='%(a.logon.logoff): %n (%M) tty: %l time: %T (%D)'

  (( $#mailpath > 0 )) && mailpath=(${^mailpath%\?*}'?new: $_')

  zstyle ':completion:*:descriptions' format '%K{white}%d%k'
  zstyle ':completion:*:messages' format '%F{green}%d%f'
  zstyle ':completion:*:warnings' format '%F{red}no matches for %d%f'
  zstyle ':completion:*:corrections' format '%K{white}%d (errors: %9F%e%f)%k'
  zstyle ':completion:*:options' auto-description "specify $cs[“]%d$cs[”]"

  add-zsh-hook precmd prompt_now_precmd
  add-zsh-hook chpwd prompt_now_adjust_width
  functions[TRAPWINCH]="${functions[TRAPWINCH]//$'\n'    prompt_now_winch}
    prompt_now_winch"
}

prompt_now_teardown () {
  emulate -L zsh

  add-zsh-hook -D precmd prompt_now_precmd
  functions[TRAPWINCH]="${functions[TRAPWINCH]//$'\n'    prompt_now_winch}"
}

prompt_now_preview () {
  local +h PS1='%# '
  prompt_preview_theme now "$@"
}

[[ -o kshautoload ]] || prompt_now_setup "$@"

      reply	other threads:[~2011-01-25 13:45 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-12-10 10:40 zle reset-prompt with prompt that is COLUMNS wide eats line above prompt’s " Nikolai Weibull
2010-12-11  7:57 ` zle reset-prompt with prompt that is COLUMNS wide eats line above prompt's " Bart Schaefer
2011-01-25 13:23   ` Nikolai Weibull [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='AANLkTi=3XBAg_LTZDPSm5vCKytQohb6sCoekGLEPDA5e@mail.gmail.com' \
    --to=now@bitwi.se \
    --cc=schaefer@brasslantern.com \
    --cc=zsh-users@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).