Tom Hale
Tom Hale

Reputation: 46795

Escape ANSI sequence of non-printing characters between \[ and \]

The bash manual says that, in the prompt, any sequences of non-printing characters should be enclosed like: \[this\]:

\[  Begin a sequence of non-printing characters.
    This could be used to embed a terminal control sequence into the prompt.

\]  End a sequence of non-printing characters.

Given a string to be included in the prompt, how can i automatically escape all ANSI control / color codes, to make the prompt display / wrap correctly under all circumstances?


Differentiation: Here i assume that a string with ANSI control codes has already been produced.

This related question assumes that the delimiters can be inserted by editing the string's generating function.

Upvotes: 0

Views: 524

Answers (2)

that other guy
that other guy

Reputation: 123470

Don't try to automate it.

The reason why Bash asks you to add the \[...\]'s manually is because the shell can't reasonably know how any given terminal will interpret any escape codes. If it was, Bash would just do it in the first place.

For example, here are a few of the many cases that the other answer fails to handle. In each case, no output is printed on my particular terminal and yet the escaping function fails to escape them:

printf '\e]1;Hello\a'  # Set window title
printf '\e[0;2;0;0;0}' # 24-bit color
printf '\e[13]'        # Unblank screen

Upvotes: 0

Tom Hale
Tom Hale

Reputation: 46795

The following will enclose ANSI control sequences in ASCII SOH (^A) and STX (^B) which are equivalent to \[ and \] respectively:

function readline_ANSI_escape() {
  if [[ $# -ge 1 ]]; then
    echo "$*"
  else
    cat  # Read string from STDIN
  fi | \
  perl -pe 's/(?:(?<!\x1)|(?<!\\\[))(\x1b\[[0-9;]*[mG])(?!\x2|\\\])/\x1\1\x2/g'
}

Use it like:

$ echo $'\e[0;1;31mRED' | readline_ANSI_escape

Or:

$ readline_ANSI_escape "$string"

As a bonus, running the function multiple times will not re-escape already escaped control codes.

Upvotes: 1

Related Questions