mawww / kakoune

mawww's experiment for a better code editor
http://kakoune.org
The Unlicense
9.97k stars 714 forks source link

Running scripts using zsh from kakoune with some (rare) constraint mess up the terminal #3742

Open Guest0x0 opened 4 years ago

Guest0x0 commented 4 years ago

Steps

Here's a small (commented) example to reproduce. Put two files in a directory: rc.kak

nop %sh{
    # bash instead of zsh will not trigger any issue
    zsh script.zsh &
}

# It is necessary to use buffer hooks here.
# The following wont't reproduce the issue:
# - hook window ClientClose .* %{ ... }
#   (or any combination of the all four except buffer + BufClose)
# - typing ":nop %sh{ echo quit >a }" explicitly
# - spawning `script.zsh` from the shell,
#   and do "echo quit >a" in the shell manually
#
# It is also necessary that this hook is triggered
# on quiting kakoune.
# If a "db" is executed before exiting kakoune, the issue
# will not be triggered.
# But sending anything except "quit" to the fifo before quiting
# is irrelevant.
hook buffer BufClose .* %{
    nop %sh{
        echo quit >a
    }
}

script.zsh

(
# The `mkfifo a` and `rm a` can be done outside kakoune
mkfifo a
# A timed loop won't trigger the issue.
# So reading from a fifo should be necessary here.
while read cmd arg <a; do
    # The key is that, the BufClose hook must make the script quit.
    # Otherwise the issue won't occur.
    if [ "$cmd" = quit ]; then
        break
    fi
# The 'read' can be moved inside the while loop.
# while loop itself is irrelevant too. Only the 'read -d' is adequate.
# The delimiter is irrelevant, but the '-d' switch is necessary
done | while read -d ' '; do
    # This command is irrelevant, just to make zsh happy
    -
done
rm a
# Redirection here is necessary,
# otherwise kakoune will wait for the script
# Redirecting to some file will trigger the issue, too.
) >/dev/null 2>&1 &

Then in the same directory, do kak -n. Inside kakoune, type :source rc.kak<ret>, then :q<ret>. Back in the terminal, type ls (or other command with formatted output).

Outcome

The output is messed up. In the same terminal, switching to a directory with many files and type ls, you can see the output messed up clearly. Here's an example output:

arch-linux.kak  exherbo.kak     ledger.kak            r.kak
                                                           asciidoc.kak    fish.kak        lisp.kak              ruby.kak
                                            awk.kak         fsharp.kak      lua.kak               rust.kak
                             cabal.kak       gas.kak         mail.kak              sass.kak
              c-family.kak    git.kak         makefile.kak          scala.kak
                                                                             clojure.kak     gluon.kak       markdown.kak          scheme.kak
                                                                cmake.kak       go.kak          mercurial.kak         scss.kak
                                                 coffee.kak      haml.kak        meson.kak             sh.kak
                                coq.kak         haskell.kak     mlb.kak               sml.kak
                crystal.kak     hbs.kak         moon.kak

Expected

The terminal should not be messed up.

Several Notes

The issue seems irrelevant to terminal emulators (tested on alacritty and uxterm without any config).

Tested on newest kakoune git version (rev ec3d7c3) and a earlier version (slightly before v2020.08.04).

Typing reset back in the terminal will fix.

The issue's condition is very strict and rare, can be easily fixed manually, and is probably related to both kakoune and zsh's internals. So feel free to just close or ignore this, if nothing hit your mind about what's happening immediately after reading the description.

lenormf commented 4 years ago

What is the shell that runs shell scopes on your system? Generally it's whatever is symlinked to from /bin/sh.

Guest0x0 commented 4 years ago

bash 4.4, on NixOS. Verified using

:echo -debug %sh{ echo $BASH_VERSION }