tilt-dev / tilt

Define your dev environment as code. For microservice apps on Kubernetes.
https://tilt.dev/
Apache License 2.0
7.6k stars 299 forks source link

Terminal output in iTerm2 looks garbled #3222

Closed dkerwin closed 4 years ago

dkerwin commented 4 years ago

I'm using Tilt with iTerm2 (Build 3.3.9) and the footer is not positioned correctly. If I run it from the builtin Terminal it works fine. My tilt version is v0.13.2, built 2020-04-16. I've attached 2 screenshots to show the difference.

terminal iTerm2
nicks commented 4 years ago

Thanks for the report! I'm pretty sure I've used Tilt with iTerm2 before, so I wonder if this is a recent regression. let me poke at it a sec

nicks commented 4 years ago

I tried iTerm2 (build 3.3.9) and was not able to reproduce this problem.

From your screenshot, it almost looks like Tilt isn't correctly computing the width of the terminal (and so lines are overflowing). But I can't find any occurrences of a bug like this in the upstream terminal UI libraries we use...

If you increase the width of the window by dragging with your mouse, does the terminal UI fix itself? (not that this is a workaround, i'm just curious if what happens sheds light on the issue)

dkerwin commented 4 years ago

Resizing the window can indeed fix it. Sometimes it gets actually worse when I resize the window. When I start in fullscreen it’s pretty much „unfixable“.

dkerwin commented 4 years ago

Happy to hop on a zoom session if seeing the problem in action would help you to track it down.

nicks commented 4 years ago

Thanks for the offer! Ya, we could try that. Here's a calendly link if you want to find a time that works for you: https://calendly.com/nick-at-tilt/30min

could you also try running:

env | grep TERM

that will print some diagnostics about your terminal env, mine looks like this:

TERM_PROGRAM=iTerm.app
TERM=xterm-256color
TERM_PROGRAM_VERSION=3.3.9
TERM_SESSION_ID=w0t0p0:E4FACA45-C76D-40B3-B3F5-031AF48CF017
ITERM_PROFILE=Default
LC_TERMINAL_VERSION=3.3.9
ITERM_SESSION_ID=w0t0p0:E4FACA45-C76D-40B3-B3F5-031AF48CF017
LC_TERMINAL=iTerm2
COLORTERM=truecolor
dkerwin commented 4 years ago

Here are my TERM* env vars:

TERM_SESSION_ID=w0t3p0:9192E82A-59FA-45A0-A27E-1E092600520A
LC_TERMINAL_VERSION=3.3.9
ITERM_PROFILE=Default
TERM_PROGRAM_VERSION=3.3.9
TERM_PROGRAM=iTerm.app
LC_TERMINAL=iTerm2
COLORTERM=truecolor
TERM=xterm-256color
ITERM_SESSION_ID=w0t3p0:9192E82A-59FA-45A0-A27E-1E092600520A
LESS_TERMCAP_mb=
LESS_TERMCAP_md=
LESS_TERMCAP_me=
LESS_TERMCAP_se=
LESS_TERMCAP_so=
LESS_TERMCAP_ue=
LESS_TERMCAP_us=
nicks commented 4 years ago

hmmm...still having trouble reproing, tried on 2 different macos machines...

as a workaround, you might be able to use tilt up --hud=false and use the web UI at http://localhost:10350/ for viewing status?

dkerwin commented 4 years ago

I'm not really blocked by it. The Web UI is fine. It's more a little inconvenience at this point

dkerwin commented 4 years ago

Hey Nick,

thanks for taking the time for the live demo today. Here is the prompt setup (~./zprezto/modules/prompt/functions/prompt_paradox_setup):

#
# A two-line, Powerline-inspired theme that displays contextual information.
#
# This theme requires a patched Powerline font, get them from
# https://github.com/Lokaltog/powerline-fonts.
#
# Authors:
#   Isaac Wolkerstorfer <i@agnoster.net>
#   Jeff Sandberg <paradox460@gmail.com>
#   Sorin Ionescu <sorin.ionescu@gmail.com>
#   Patrick Bos <egpbos@gmail.com>
#
# Screenshots:
#   http://i.imgur.com/0XIWX.png
#

# Load dependencies.
pmodload 'helper'

# Define variables.
_prompt_paradox_current_bg='NONE'
_prompt_paradox_segment_separator='⮀'
_prompt_paradox_start_time=$SECONDS

function prompt_paradox_start_segment {
  local bg fg
  [[ -n "$1" ]] && bg="%K{$1}" || bg="%k"
  [[ -n "$2" ]] && fg="%F{$2}" || fg="%f"
  if [[ "$_prompt_paradox_current_bg" != 'NONE' && "$1" != "$_prompt_paradox_current_bg" ]]; then
    print -n " $bg%F{$_prompt_paradox_current_bg}$_prompt_paradox_segment_separator$fg "
  else
    print -n "$bg$fg "
  fi
  _prompt_paradox_current_bg="$1"
  [[ -n "$3" ]] && print -n "$3"
}

function prompt_paradox_end_segment {
  if [[ -n "$_prompt_paradox_current_bg" ]]; then
    print -n " %k%F{$_prompt_paradox_current_bg}$_prompt_paradox_segment_separator"
  else
    print -n "%k"
  fi
  print -n "%f"
  _prompt_paradox_current_bg=''
}

function prompt_paradox_build_prompt {
  prompt_paradox_start_segment black default '%(?::%F{red}✘ )%(!:%F{yellow}⚡ :)%(1j:%F{cyan}⚙ :)%F{blue}%n%F{red}@%F{green}%m%f'
  prompt_paradox_start_segment blue black '$_prompt_paradox_pwd'

  if [[ "${(e)k8s_info[context]}" == "internal" ]]; then
    prompt_paradox_start_segment cyan black '🐝  k8s: ${(e)k8s_info[context]}'
  else
    prompt_paradox_start_segment magenta white '☠️  k8s: ${(e)k8s_info[context]}'
  fi

  if [[ -n "$git_info" ]]; then
    prompt_paradox_start_segment green black '${(e)git_info[ref]}${(e)git_info[status]}'
  fi

  if [[ -n "$python_info" ]]; then
    prompt_paradox_start_segment white black '${(e)python_info[virtualenv]}'
  fi

  prompt_paradox_end_segment
}

prompt_paradox_print_elapsed_time() {
  local end_time=$(( SECONDS - _prompt_paradox_start_time ))
  local hours minutes seconds remainder

  if (( end_time >= 3600 )); then
    hours=$(( end_time / 3600 ))
    remainder=$(( end_time % 3600 ))
    minutes=$(( remainder / 60 ))
    seconds=$(( remainder % 60 ))
    print -P "%B%F{red}>>> elapsed time ${hours}h${minutes}m${seconds}s%b"
  elif (( end_time >= 60 )); then
    minutes=$(( end_time / 60 ))
    seconds=$(( end_time % 60 ))
    print -P "%B%F{yellow}>>> elapsed time ${minutes}m${seconds}s%b"
  elif (( end_time > 10 )); then
    print -P "%B%F{green}>>> elapsed time ${end_time}s%b"
  fi
}

function prompt_paradox_precmd {
  setopt LOCAL_OPTIONS
  unsetopt XTRACE KSH_ARRAYS

  # Format PWD.
  _prompt_paradox_pwd=$(prompt-pwd)

  # Get Git repository information.
  if (( $+functions[git-info] )); then
    git-info
  fi

  # Get Python environment information.
  if (( $+functions[python-info] )); then
    python-info
  fi

  # Get kubernetes context
  if (( $+functions[k8s-info] )); then
    k8s-info
  fi

  # Calculate and print the elapsed time.
  prompt_paradox_print_elapsed_time
}

function prompt_paradox_preexec {
  _prompt_paradox_start_time="$SECONDS"
}

function prompt_paradox_setup {
  setopt LOCAL_OPTIONS
  unsetopt XTRACE KSH_ARRAYS
  prompt_opts=(cr percent sp subst)

  # Load required functions.
  autoload -Uz add-zsh-hook

  # Add hook for calling git-info before each command.
  add-zsh-hook preexec prompt_paradox_preexec
  add-zsh-hook precmd prompt_paradox_precmd

  # Set editor-info parameters.
  zstyle ':prezto:module:editor:info:completing' format '%B%F{red}...%f%b'
  zstyle ':prezto:module:editor:info:keymap:primary' format '%B%F{blue}❯%f%b'
  zstyle ':prezto:module:editor:info:keymap:primary:overwrite' format '%F{red}♺%f'
  zstyle ':prezto:module:editor:info:keymap:alternate' format '%B%F{red}❮%f%b'

  # Set git-info parameters.
  zstyle ':prezto:module:git:info' verbose 'yes'
  zstyle ':prezto:module:git:info:action' format ' ⁝ %s'
  zstyle ':prezto:module:git:info:added' format ' ✚'
  zstyle ':prezto:module:git:info:ahead' format ' ⬆'
  zstyle ':prezto:module:git:info:behind' format ' ⬇'
  zstyle ':prezto:module:git:info:branch' format '⭠ %b'
  zstyle ':prezto:module:git:info:commit' format '➦ %.7c'
  zstyle ':prezto:module:git:info:deleted' format ' ✖'
  zstyle ':prezto:module:git:info:dirty' format ' ⁝'
  zstyle ':prezto:module:git:info:modified' format ' ✱'
  zstyle ':prezto:module:git:info:position' format '%p'
  zstyle ':prezto:module:git:info:renamed' format ' ➙'
  zstyle ':prezto:module:git:info:stashed' format ' S'
  zstyle ':prezto:module:git:info:unmerged' format ' ═'
  zstyle ':prezto:module:git:info:untracked' format ' ?'
  zstyle ':prezto:module:git:info:keys' format \
    'ref' '$(coalesce "%b" "%p" "%c")' \
    'status' '%s%D%A%B%S%a%d%m%r%U%u'

  # %v - virtualenv name.
  zstyle ':prezto:module:python:info:virtualenv' format 'virtualenv:%v'

  # Define prompts.
  PROMPT='
${(e)$(prompt_paradox_build_prompt)}
 ${editor_info[keymap]} '
  RPROMPT='%F{blue}[%F{green}%D{%H:%M:%S}%F{blue}]%f'
  SPROMPT='zsh: correct %F{red}%R%f to %F{green}%r%f [nyae]? '
}

prompt_paradox_setup "$@"
nicks commented 4 years ago

i have a repro case! trying to narrow it down. Also i really like this zprezto prompt and might keep it!

nicks commented 4 years ago

@dkerwin if in iTerm2, you go to Session -> Edit Session -> Text, do you have an option called "Ambiguous characters are double width"? This is what I see when I turn it on:

Screen Shot 2020-04-22 at 3 20 18 PM

which looks very similar to your screenshot. I think what's happening here is that our layout code is treating certain characters as single-width, but the terminal is treating them as double-width, so we're making bad layout calculations. To be clear, I think the bug might be in the Tilt code, though might mean we have to call some terminal function to figure out the layout width of a character.

dkerwin commented 4 years ago

This indeed the issue. After disabling the setting the UI renders correctly. No more overflowing lines. Thank you so much!

nicks commented 4 years ago

Ugh, I poked around a bit, and I'm not sure if it's possible for us to fix this. https://github.com/gdamore/tcell/issues/203#issuecomment-378815682 It looks like iTerm2 is breaking the unicode recommendation here, and there are no real terminal APIs to even detect it's doing this...oh well, at least I learned a lot about unicode ambiguous-width characters today! :joy: