Wyświetlać rzeczy poniżej pytania po znaku zachęty powłoki?

21

Powiedzmy, że mój monit wygląda tak (_ reprezentuje mój kursor)

~ % _

Czy jest jakiś sposób, w jaki mogę sprawić, aby wyglądał tak

~ % _
[some status]

Pytanie pierwotnie dotyczyło zsh, ale teraz ma inne odpowiedzi.

ksenoterracid
źródło
Jak o ekranie + buobu ?: launchpad.net/byobu , a może kmandla.wordpress.com/2010/01/03/... do screenów
Janus

Odpowiedzi:

17

Wydaje się, że działają następujące ustawienia. Tekst w drugim wierszu znika, jeśli wiersz polecenia przepełnia pierwszy wiersz. preexecFunkcja kasuje drugą linię przed uruchomieniem polecenia; jeśli chcesz to zachować, zmień na preexec () { echo; }.

terminfo_down_sc=$terminfo[cud1]$terminfo[cuu1]$terminfo[sc]$terminfo[cud1]
PS1_2='[some status]'
PS1="%{$terminfo_down_sc$PS1_2$terminfo[rc]%}%~ %# "
preexec () { print -rn -- $terminfo[el]; }

%znaki ucieczki są udokumentowane w instrukcji zsh ( man zshmisc).

Terminfo to interfejs API dostępu do terminala. Zsh ma terminfomoduł, który daje dostęp do bazy danych opisów terminali: $terminfo[$cap]jest sekwencją znaków, które należy wysłać, aby skorzystać z możliwości terminala $cap, tj. Uruchomić jego $cappolecenie. Aby man 5 terminfouzyskać więcej informacji, zobacz (w systemie Linux numer sekcji może się różnić w przypadku innych unikatów).

Sekwencja działań jest następująca: przesuń kursor w dół o jedną linię ( cud1), a następnie w górę ( cuu1); zapisz pozycję kursora ( sc); przesuń kursor w dół o jedną linię; wydrukować [some status]; przywrócić pozycję kursora. Bit „góra i dół” na początku jest konieczny tylko w przypadku, gdy monit znajduje się w dolnej linii ekranu. Wiersz preexec usuwa drugi wiersz ( el), aby nie pomylić go z danymi wyjściowymi polecenia.

Jeśli tekst w drugim wierszu jest szerszy niż terminal, wyświetlacz może być zniekształcony. Użyj Ctrl+ Lw szczypcie do naprawy.

Gilles „SO- przestań być zły”
źródło
5

Oto bashodpowiednik rozwiązania Zsh Gillesa. Bash nie ma natywnego modułu terminfo, ale tputpolecenie (w pakiecie terminfo) robi to samo.

PS1_line1='\w \$ '
PS1_line2='[some status]'

if (tput cuu1 && tput sc && tput rc && tput el) >/dev/null 2>&1
then
    PS1="
\[$(tput cuu1; tput sc)\]
\[${PS1_line2}$(tput rc)\]${PS1_line1}"
    PS2="\[$(tput el)\]> "
    trap 'tput el' DEBUG
else
    PS1="$PS1_line2 :: $PS1_line1"
fi

Jeśli terminal nie obsługuje jednej z możliwości, wróci do wiersza z jedną linią.

trapLinia jest hacky sposób naśladować zsh za preexecfunkcją. Aby uzyskać więcej informacji, zobacz /superuser/175799/

EDYCJA : Ulepszony skrypt oparty na komentarzach Gillesa.

Jander
źródło
@Gilles: Dzięki za wkład! Myślę, że teraz działa lepiej. Próbowałem bash 4.1.5 w gnome-terminal i xterm oraz bash 3.2.48 w terminalu OSX.
Jander