emacs terminal bash (PS1) prompt duplicated

2019-08-13 22:01发布

问题:

This is a bit of a convoluted question, but here goes nothing! I've recently updated my bash prompt to the nice version appearing in the last post of this thread: Bash: custom PS1 with nice working directory path. The relevant bash code (from that thread post) is copied here:

# define the awk script using heredoc notation for easy modification
MYPSDIR_AWK=$(cat << 'EOF'
BEGIN { FS = OFS = "/" }
{ 
   if (length($0) > 16 && NF > 4)
      print $1,$2,".." NF-4 "..",$(NF-1),$NF
   else
      print $0
}
EOF
)

# my replacement for \w prompt expansion
export MYPSDIR='$(echo -n "${PWD/#$HOME/~}" | awk "$MYPSDIR_AWK")'

# the fancy colorized prompt: [0 user@host ~]%
# return code is in green, user@host is in bold/white
export PS1='[\[\033[1;32m\]$?\[\033[0;0m\] \[\033[0;1m\]\u@\h\[\033[0;0m\] $(eval "echo ${MYPSDIR}")]% '

# set x/ssh window title as well
export PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME%%.*} $(eval "echo ${MYPSDIR}")\007"'

This prompt looks roughly like so (in non-emacs terminals):

[0 user@host ~/my_dir]%

Where the "0" above is green and the "user@host" is bold. (Note that the "0" can be all sorts of numbers, and represents the return value of the last command.)

The issue I'm experiencing is specific to shells running within emacs (and it occurs for most variants of terminal-interaction within emacs: 'term', 'ansi-term', 'shell', and 'eshell'). The prompt appears twice (and slightly broken) in emacs terminals, like so:

0;user@host ~/my_dir[0 user@host ~/my_dir]%

The 'second' version of the prompt, starting from and including the "[" looks just fine. It's the preceding text, which appears without any styling (i.e. no green and no bold). So, emacs must be interpreting some portion of the prompt as input, and my guess is the color or bold escaped indicators attached to the "0" and "user@host" portions of the prompt?

Might anyone know how to tell emacs to interpret the escapes correctly? Or, alternatively, how to modify the prompt-setting commands such that both emacs will not hate it and it'll still work in non-emacs terminals? And maybe even another alternative: how to add a test for the terminal type ('eterm-color' within emacs) with a modified string that is emacs-friendly?

回答1:

The error comes from the export PROMPT_COMMAND=... statement.

You can avoid this being read in your configuration, by checking whether you have a shell running inside emacs or not. Here the environment variable INSIDE_EMACS becomes handy. From the Emacs manual (Sect. 32.7):

Emacs sets the environment variable INSIDE_EMACS in the subshell to ‘version,comint’, where version is the Emacs version (e.g., ‘24.1’). Programs can check this variable to determine whether they are running inside an Emacs subshell

In your example, you want export PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME%%.*} $(eval "echo ${MYPSDIR}")\007" only being executed when you are not in emacs, otherwise you get this nasty "double prompt". The following conditional statement in your code will help.

if [ -z "$INSIDE_EMACS" ];
 then
  export PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME%%.*} $(eval "echo ${MYPSDIR}")\007"'
 else
  export PROMPT_COMMAND=''
fi

It checks whether you are not inside emacs, and only then the PROMPT_COMMAND variable is set to your desired value.



回答2:

The extra display is coming from the PROMPT_COMMAND variable's contents. emacs appears not to understand the OSC 0 title setting xterm escape sequence and so prints out the output.