0

My zsh config contains setopt PROMPT_SUBST. When I use command substitution in a shell command, I see it is executed twice. This could cause slowdowns or even bugs in my scripting.

% setopt PROMPT_SUBST
% echo $(echo executed >&2)
executed
executed

I found it is happening due to my setting the xterm window title in preexec(). (Note: I'm not using xterm, but the same code works for many terminals, like WSL terminal, wslterm, and tmux.) How can I set the title in a way that doesn't execute the command substitutions? Note: the current title setting code is:

preexec () {
    print -Pn "\ek$2\e\\"
}
precmd () { 
    print -Pn "\ekzsh\e\\"
}
2
  • Why would you use -P in the first place? Jul 3 '20 at 12:01
  • Sounds like you'd want print -rn $'\ek'$2$'\e\\' here Jul 3 '20 at 12:01
0

Unfortunately all terminals are different and the only way seems to be to write a different preexec and precmd for each terminal. To get working tab titles in tmux, I had to add set -g allow-rename on to .tmux.conf, or to execute tmux set -g allow-rename on. The functions to set the title without executing the command are:

preexec () { 
    local cmd=$2
    printf "\033k%s\033\\" $cmd
}
precmd () {
    printf "\033kzsh\033\\"
}

The more comprehensive solution would need different technique for each $TERM. Note that tmux is not detected using $TERM.

if [[ -n $TMUX ]]; then
    preexec () { 
        local cmd=$2
        printf "\033k%s\033\\" $cmd
    }
    precmd () { 
        printf "\033kzsh\033\\"
    }
else
    # Set xterm/terminal/whatever titles when commands are running:
    case $TERM in
        linux)
            ;;
        *xterm*|rxvt|rxvt-unicode|rxvt-256color|(dt|k|E)term)
            preexec() {
                # TODO
            }
            precmd() {
                # TODO
            }
            ;;
        *screen*)
            preexec() {
                # TODO
            }
            precmd() {
                # TODO
            }
            ;;
    esac
fi

Some preexec commands worth testing in each terminal are:

print -Pn "\e]0;${cmd}\a"
print -Pn "\ek${cmd}\e\\"
3
  • 1
    The first argument to printf is the format, you shouldn't put external data in there. Jul 3 '20 at 12:02
  • @StéphaneChazelas Good catch! Fixed.
    – piojo
    Jul 3 '20 at 12:33
  • 1
    In xterm-like terminals, it would be printf '\033]2;%s\a' "$cmd" to set the title. With 0, it sets both title and icon name (which you may or may not want). Jul 3 '20 at 13:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.