2

I have a script, that when run sometimes/often outputs an "unescaped" ANSI escape sequence when encountering this line:

vim -X -u NONE -c "helptags ~/.vim/plugged/vim-fugitive/doc" -c q

The result looks like this:

enter image description here

I have no idea why this happens, as running the command on its own seems to never produce this "garbage". It only ever happens if the line is run; commenting it out removes the issue. Even weirder is the fact that it sometimes does not happen. It could be good, then I do something and it appears. The output of running the script is fine. Once it manifests, though, it seems persistent (* not true, see below) ... opening another terminal tab will usually show the problem.

Any idea what is happening here? Is vim picking up no some terminal setting ($TERM?) and interfering with the output? Or is there something else going on?

My utility functions for colored output is here, should it matter.

EDIT:

  • It turns out that changing the PS1 prompt to something like $ made the issue go away when it materialized, but re-instating the prompt to the colorful one did not bring the issue back, so I have a hard time finding some determinism here.

PS1 prompt setup is done here:

set_prompt(){
    local user=$(green "\u")
    local host=$(dark_yellow "\h")
    local workdir=$(pink "\w")
    local gitbranch=$(dark_red \$\(__git_ps1  "\(%s\)" \))
    local at=$(dark_grey at)
    local in=$(dark_grey in)
    export PS1="\n${user} ${at} ${host} ${in} ${workdir} ${gitbranch}"$'\n\$ '
}

Now set it. If any of these colors are later overridden, then just rerun set_prompt

set_prompt

and uses these utility functions and variables:

# Color escape codes @see http://misc.flogisoft.com/bash/tip_colors_and_formatting
# Use \033 instead of \e. Workes better across platforms
# \e works in PS1 prompts, but not other places
c_X_reset_all='\033[0m' #stop code for color escape
c_X_bold='\033[21m'
c_X_reset_bold='\033[21m'
c_green='\033[01;32m'
c_blue='\033[01;34m'
c_pink='\033[01;35m'
c_dark_grey='\033[90m'

c_dark_yellow='\033[38;5;178m' c_dark_red='\033[38;5;196m'

green(){ echo -n -e ${c_green}$@${c_X_reset_all} }

blue(){ echo -n -e ${c_blue}$@${c_X_reset_all} }

pink(){ echo -n -e ${c_pink}$@${c_X_reset_all} }

dark_grey(){ echo -n -e ${c_dark_grey}$@${c_X_reset_all} }

dark_yellow(){ echo -n -e ${c_dark_yellow}$@${c_X_reset_all} }

dark_red(){ echo -n -e ${c_dark_red}$@${c_X_reset_all} }

Prompt (pre-changes)

This is the prompt before implementing the changes from the comments:

$ perl -e 'print quotemeta($ENV{PS1})'
\\n\[01\;32m\\u\[0m\ \[90mat\[0m\ \[38\;5\;178m\\h\[0m\ \[90min\[0m\ \[01\;35m\\w\[0m\ \[38\;5\;196m\$\(__git_ps1\ \\\(\%s\\\)\ \)\[0m\
\\\$\

You can see all the \033 bits being gone and replaced with \. That is because it is the octal representation of the ESC character (27 in decimal, 1B in hex) and is now shown as \ in the output (\033[ becomes \]).

Prompt (after introducing escape sequences)

This seems to have fixed the issue

The comments suggested introducing escape sequences around non-printable characters. That seems to have changed things a bit, as the ESC characters are no longer being replaced:

$ perl -e 'print quotemeta($ENV{PS1})'
\\n\\\[\\033\[01\;32m\\\]\\u\ \\\[\\033\[90m\\\]at\ \\\[\\033\[38\;5\;178m\\\]\\h\ \\\[\\033\[90m\\\]in\ \\\[\\033\[01\;35m\\\]\\w\ \\\[\\033\[38\;5\;196m\\\]\(master\)\\\[\\033\[00m\\\]\
\\\$\
oligofren
  • 1,150
  • 2
    What happens if you run PS1='$ ' and then try the command again? Is the terminal still garbled? If so, you probably have a syntax error in your PS1 variable. – terdon Jan 16 '23 at 12:12
  • 1
  • @terdon I have an issue with determinism when testing this out. The issue can appear with a fresh Terminal and be present in a new fresh tab and then another tab opening the same directory could not show it. So weird. BUT to answer your question: this removed the issue when it appeared. So maybe something to do with escape characters? But again: hard to tell due to the lack of determinism thing. – oligofren Jan 17 '23 at 13:39
  • Ah, at least we're getting somewhere. I am pretty sure the problem is as described in the answer to the question I linked you to earlier. You need \[ and \] around all non-printing characters such as color codes. It's kind of hard to get exactly what your PS1 is from your code (this approach makes for clean, readable code, but it's tricky to see what the final PS1 will be), but try printf '%s\n' "$PS1" and look for non-printing characters (color codes, most likely) that are not in \[ \]. – terdon Jan 17 '23 at 14:08
  • I refactored the prompt setting to add the escape characters earlier today, so I guess I will know in a few days whether or not the issue is gone :) https://github.com/fatso83/dotfiles/commit/c738d87183c1ecfe1030c100439097d71545db82 – oligofren Jan 17 '23 at 16:11
  • Doing that printf command will not show the non-printing characters. It just shows the output colored: \n\u at \h in \w $(__git_ps1 \(%s\) ) \$ (hard to show color in black and white). – oligofren Jan 17 '23 at 16:17
  • Oh duh, of course! Try perl -e 'print quotemeta($ENV{PS1})'. That will likely add many unnecessary \ but it should give you a better idea. – terdon Jan 17 '23 at 16:22
  • Oh, that was more like. I have added the output of that command pre and post escape sequence. Seems to definitely affect what ends up in the terminal. – oligofren Jan 18 '23 at 10:40

0 Answers0