emacs-libvterm icon indicating copy to clipboard operation
emacs-libvterm copied to clipboard

Numerous problems with zsh integration code

Open rjekker opened this issue 2 years ago • 2 comments

The current integration example code in /etc/emacs-vterm-zsh.sh contains several problems.

To start there is the related bug #574 where the code to add a chpwd hook is incorrect. To correct this, you would write something like this:

vterm_update_buffer_title (){
    print -Pn "\e]2;${EMACS_VTERM_BUFFER_TITLE:-%m:%2~}\a" 
}
add-zsh-hook -Uz chpwd vterm_update_buffer_title

The problem is that now you are printing information to stdout even from within shell scripts that use cd; that means you WILL be polluting output files with this.

A hook will also only set your buffer title after the first directory change; I like to see it immediately when vterm starts.

So a better solution would be to not use a hook at all and just add this to the prompt.

Another problem is that printing extra information in the prompt will cause any RPROMPT in the zsh to shift location. To prevent that, we have to put the escape codes in {%..%}.

My config now looks like this, which solves all those problems:

     emacs_vterm_prompt () {
        buffer_title_update=$(print -Pn "\e]2;%2~$\a")
        pwd_update=$(print -Pn "\e]51;A$(whoami)@$(hostname):$(pwd)\e")
        prompt_end=$(print "%{$buffer_title_update$pwd_update%}\\")
        PROMPT="$PROMPT$prompt_end"
    }
    autoload -U add-zsh-hook
    add-zsh-hook precmd emacs_vterm_prompt

Note that the prompt is now set in a precmd hook, which makes this code play nice with other code that changes the prompt like ohmyzsh themes.

By the way, if we move the double slashes \\ at the end of prompt_end inside the %}:

prompt_end=$(print "%{$buffer_title_update$pwd_update\\%}")

This crashes my emacs every single time.

rjekker avatar May 17 '23 21:05 rjekker

See also this comment.

noctuid avatar Jun 08 '23 12:06 noctuid

For me, this almost works. The only problem is because of the mentioned \\ at the end of prompt_end, tab-completion duplicates characters (because \\ has nonzero length, I think). Of course, moving it inside the %} crashes Emacs. Here's what worked for me:

vterm_printf() {
    # update buffer title
    print -Pn "\e]2;%2~\a"

    if [ -n "$TMUX" ] && ([ "${TERM%%-*}" = "tmux" ] || [ "${TERM%%-*}" = "screen" ]); then
        # Tell tmux to pass the escape sequences through
        printf "\ePtmux;\e\e]%s\007\e\\" "$1"
    elif [ "${TERM%%-*}" = "screen" ]; then
        # GNU screen (screen, screen-256color, screen-256color-bce)
        printf "\eP\e]%s\007\e\\" "$1"
    else
        printf "\e]%s\e\\" "$1"
    fi

}

vterm_prompt_end() {
    prompt_end=$(vterm_printf "51;A$USER@$HOST:$PWD")
    PROMPT="$PROMPT%{$prompt_end%}"
}

autoload -U add-zsh-hook
add-zsh-hook precmd vterm_prompt_end

Lawqup avatar Sep 06 '23 16:09 Lawqup