Wyczyść stare wiersze zachęty, aby zaoszczędzić miejsce na przewijaniu

11

Mój motyw terminalu był taki,

zabezpieczyć je wcześniej

Ale myślałem, że szybkie marnuje tyle miejsca. Później wpadłem na pomysł, że mogę wyczyścić monit za każdym razem, gdy uruchamiam polecenie. Korzystałem z bash, jednym z rozwiązań jest użycie preexec_invoke_execfunkcji.

Używam następującego polecenia, aby wyczyścić ostatnie znaki zachęty:

echo -ne "\033[1A\033[K\033[1A\033[K\033[31;1m$ \033[0m"

Aby terminal był bardzo czysty, taki jak ten,

wprowadź opis zdjęcia tutaj

Ale teraz mój problem polega na tym, że będzie problem, jeśli chcę używać wielu poleceń w jednym wierszu , powiedzmy, kiedy używam for i in ....

Oto pełna wersja funkcji w moim .bashrc,

preexec () { echo -ne "\033[1A\033[K\033[1A\033[K\033[31;1m$ \033[0m"; echo -n "$1"; echo -ne "  \033[37;2m["; echo -n "$2"; echo -ne "]\033[0m\n"; }
preexec_invoke_exec () {
    [ -n "$COMP_LINE" ] && return  # do nothing if completing
    [ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # don't cause a preexec for $PROMPT_COMMAND
    local this_command=`history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//g"`;
    local this_pwd=`pwd`; 
    preexec "$this_command" "$this_pwd"
}
trap 'preexec_invoke_exec' DEBUG
Libin Wen
źródło
Sztuczka Zsh Glypha Lefkowitza - fajnie!
2
Łatwe rozwiązanie zaczyna się od zsh
Gilles „SO- przestań być zły”
Brakowało mi tam twojego pytania ...
David Hoelzer
@DavidHoelzer Cóż, jeśli wykonasz for i in $(seq 1 10); do ls; donejego funkcję, wynik komend iteracyjnych zostanie „połknięty”, że tak powiem. Więc OP chciał zdezynfekować zachowanie, jednocześnie umożliwiając to pytanie. Powodem, dla którego to popieram, jest zainteresowanie świadomością powłoki, użyteczność, informacje zwrotne i przenośność. Link, który umieściłem w poprzednim komentarzu, prowadzi do posta na stronie superużytkownika - zadali sobie trud przypisania tego fragmentu kodu, więc jest to prototyp, który emuluje natywną funkcjonalność zsh (co moim zdaniem jest interesujące), w postaci funkcji pułapki tutaj.

Odpowiedzi:

3

Najpierw preexec_invoke_execnależy zmodyfikować, aby zapobiec wielokrotnemu wykonywaniu preexec. Zmodyfikuj również, preexecaby uwzględnić faktyczną liczbę wierszy w $PS1:

preexec () { 
    # delete old prompt; one "\e[1A\e[K" per line of $PS1
    for (( i=0, l=$(echo -e $PS1 | wc -l) ; i < l ; i++ ))
    do             
        echo -ne "\e[1A\e[K"
    done
    # replacement for prompt
    echo -ne "\e[31;1m$ \e[0m"
    echo -n "$1"
    echo -ne "  \e[37;2m["
    echo -n "$2"
    echo -e "]\e[0m"
}

preexec_invoke_exec () {
    [ -n "$DONTCLEANPROMPT" ] && return
    DONTCLEANPROMPT=x
    [ -n "$COMP_LINE" ] && return  # do nothing if completing
    [ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # don't cause a preexec for $PROMPT_COMMAND
    local this_command=`history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//g"`;
    local this_pwd=`pwd`
    preexec "$this_command" "$this_pwd"
}

trap 'preexec_invoke_exec' DEBUG

PROMPT_COMMAND='unset DONTCLEANPROMPT'

Aby preexecponownie uruchomić, DONTCLEANPROMPTmusi być albo rozbrojony, albo ustawiony na ''. Odbywa się to za pomocą PROMPT_COMMAND, który jest uruchamiany tuż przed wydaniem podstawowego monitu. Dlatego preexecbędzie uruchamiany raz i tylko raz dla każdej linii poleceń.

Adaefon
źródło
Twoje rozwiązanie rozwiązuje problem z forpętlą! Dziękuję Ci! Jest jeszcze jedna niedogodność. Co się stanie, jeśli wykonasz lspolecenie i uzyskasz wynik, a następnie zrobisz inny ls, zobaczysz, że ostatni wiersz poprzedniego wyjścia zostanie usunięty ... czy masz pomysł, jak to rozwiązać?
1
Prawdopodobnie używasz monitu z tylko jedną linią. Zmień pierwsze echo prexecna drukowane "\033[1A\033[K\033[31;1m$ \033[0m", czyli tylko jedno \033[1A\033[K(przesuń 1 linię w górę, usuń do końca linii) zamiast dwóch.
Adaephon
Bez skazy! Bardzo dziękuję za rozwiązanie i czas poświęcony na wyjaśnienie. To rozwiązuje problem OP i jeszcze bardziej debuguje rozwiązanie. Czyni to użytecznym dla wszystkich! Twoje zdrowie!