Wznów Zsh-Terminal (OS X Lion)

17

OS X Lion ma funkcję „Wznów”, tzn. Po ponownym otwarciu aplikacji przywraca wszystkie okna i ich zawartość. To działa również w Terminalu. Ale jeśli użyjesz Zsh zamiast Bash, nie przywróci on otwartego katalogu. Jak mogę to naprawić?

Simon Perepelitsa
źródło
Powiązane z odpowiedziami poniżej: uświadomienie terminal.app, że katalog jest przydatny, jest również przydatne do otwierania nowych terminali w tym samym katalogu, co bieżący
nhooyr

Odpowiedzi:

18

AKTUALIZACJA : Nie jest to całkowicie poprawne, z powodów wymienionych w komentarzach. Skorzystaj z odpowiedzi poniżej . Dzięki @ChrisPage za włożenie dodatkowej mile :)

Odpowiedź można znaleźć za pomocą inżynierii odwrotnej, w jaki sposób bash to robi /etc/bashrc. Próbowałem wielu podejść z całej sieci, ale sposób Apple wydaje się działać najlepiej (idź rysunek).

W swoim .zshrcdodaj następujące

# Set Apple Terminal.app resume directory
if [[ $TERM_PROGRAM == "Apple_Terminal" ]] && [[ -z "$INSIDE_EMACS" ]] {
  function chpwd {
    local SEARCH=' '
    local REPLACE='%20'
    local PWD_URL="file://$HOSTNAME${PWD//$SEARCH/$REPLACE}"
    printf '\e]7;%s\a' "$PWD_URL"
  }

  chpwd
}

Happy wznowienia.

Dla wyjaśnienia, ta odpowiedź dotyczy tajemniczej wiadomości w preferencjach Terminal.app systemu OS X Lion:

** Programy powiadamiają terminal o bieżącym katalogu roboczym za pomocą sekwencji specjalnych. Może być konieczne skonfigurowanie powłoki lub innych programów, aby włączyć to zachowanie. *

Ta odpowiedź działa, gdy używasz zsh jako powłoki. Wznowienie terminalu dla bash zostało już zaimplementowane przez Apple.

captainpete
źródło
1
Prawdopodobnie nie jest to duża rzecz w praktyce, ale widzę, że stock / etc / bashrc ma ostatnią linię, chpwdjak printf '\e]7;%s\a' "$PWD_URL"w przypadku podwójnych cudzysłowów. Dzięki za wskazówkę.
Ryan McCuaig
To teraz trafia do oh-my-zsh (patrz github.com/robbyrussell/oh-my-zsh/pull/522 ). Musisz upewnić się, że masz włączoną wtyczkę osx w swoim zshrc.
Ryan McCuaig,
2
Zauważ też, że ten kod koduje tylko spacje procentowo. Aby uzyskać punkty bonusowe, ustaw kodowanie procentowe wszystkich niedozwolonych znaków adresu URL (i sprawdź, czy możesz to zrobić bez wywoływania programów). Jest to ważne, jeśli chcesz, aby działało ze wszystkimi prawidłowymi nazwami ścieżek. Ponadto niektóre znaki nie są nawet uważane za część sekwencji specjalnych, więc kodowanie procentowe jest wymagane, aby dostać się do terminala. Byłem w stanie to zrobić dla bash, ale nie próbowałem tego przetestować z zsh.
Chris Page
1
Cytaty wokół „$ PWD_URL” są wymagane, aby zapobiec zmungowaniu nazwy ścieżki. EDYCJA: Jest to wymagane w bash, ale opcjonalne w zsh. Wolę używać cytatów konsekwentnie, aby były przenośne.
Chris Page
Dzięki Ryan, Chris. Zaktualizowałem skrypt, aby używać podwójnych cudzysłowów dla zachowania spójności.
captainpete
27

Oto moja adaptacja / etc / bashrc dla zsh. Podałem kodowanie procentowe wszystkich znaków URL, które tego wymagają, co jest ważne, jeśli chcesz, aby działało ze wszystkimi prawidłowymi nazwami plików i katalogów.

To rejestruje precmdprzechwycenie, które pozwala zarejestrować więcej niż jedną funkcję w innych skryptach i plikach konfiguracyjnych.

ZAKTUALIZOWANY Marzec 2019: Ustaw LC_ALLna pusty, aby nie zastępował LC_CTYPE. Służy precmddo aktualizowania katalogu roboczego przy każdym pytaniu zamiast chpwddo aktualizowania go za każdym razem, gdy jest zmieniany - potoki poleceń mogą go tymczasowo zmienić i terminal nie powinien ich wyświetlać. Pomocne może być również zaktualizowanie stanu terminala w przypadku każdego monitu na wypadek, gdyby został on zmieniony podczas poprzedniego polecenia. Służy printf -vdo jawnego zapisu do zmiennej zamiast używania składni podpowłoki.

# Tell the terminal about the working directory whenever it changes.

if [[ "$TERM_PROGRAM" == "Apple_Terminal" ]] && [[ -z "$INSIDE_EMACS" ]]; then

    update_terminal_cwd() {
        # Identify the directory using a "file:" scheme URL, including
        # the host name to disambiguate local vs. remote paths.

        # Percent-encode the pathname.
        local url_path=''
        {
            # Use LC_CTYPE=C to process text byte-by-byte. Ensure that
            # LC_ALL isn't set, so it doesn't interfere.
            local i ch hexch LC_CTYPE=C LC_ALL=
            for ((i = 1; i <= ${#PWD}; ++i)); do
                ch="$PWD[i]"
                if [[ "$ch" =~ [/._~A-Za-z0-9-] ]]; then
                    url_path+="$ch"
                else
                    printf -v hexch "%02X" "'$ch"
                    url_path+="%$hexch"
                fi
            done
        }

        printf '\e]7;%s\a' "file://$HOST$url_path"
    }

    # Register the function so it is called at each prompt.
    autoload add-zsh-hook
    add-zsh-hook precmd update_terminal_cwd
fi
Chris Page
źródło
Dzięki, zaakceptowane rozwiązanie nie działało dla mnie, ale to działa.
eelco,
Ten też działa dla mnie.
sikachu
4
Należy również zauważyć, że to rozwiązanie jest już w och-my-zsh , wystarczy aktywować terminalappwtyczkę.
Simon
1
Dla jasności @ Simon oznacza, że ​​jest to teraz oh-my-zsh, dodane, ponieważ ta odpowiedź została napisana.
Chris Page
To prawda @ChrisPage, przepraszam za niejednoznaczne sformułowanie (angielski nie jest moim językiem ojczystym). Chciałem tylko powiedzieć, że nie musisz wklejać tego do swojego .zprofileczy cokolwiek innego, tak jak to zrobiłem, zanim zdałem sobie sprawę, że w rzeczywistości jest dostępny oh-my-zsh. Jest to dokładnie to samo rozwiązanie i zasługujesz na uznanie.
Simon