Afficher des éléments sous l'invite à l'invite du shell?

21

Disons que mon invite ressemble à ceci (le _ représente mon curseur)

~ % _

Existe-t-il un moyen de le faire ressembler à ceci

~ % _
[some status]

La question était à l'origine sur zsh, mais a maintenant d'autres réponses.

xénoterracide
la source
Que diriez - vous ?: écran + buobu launchpad.net/byobu , et peut - être kmandla.wordpress.com/2010/01/03/... captures d' écran
Janus

Réponses:

17

Les paramètres suivants semblent fonctionner. Le texte de la deuxième ligne disparaît si la ligne de commande déborde de la première ligne. La preexecfonction efface la deuxième ligne avant d'exécuter la commande; si vous voulez le conserver, changez pour 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]; }

%les échappements sont documentés dans le manuel zsh ( man zshmisc).

Terminfo est une API d'accès au terminal. Zsh dispose d'un terminfomodule qui donne accès à la base de données de description du terminal: $terminfo[$cap]c'est la séquence de caractères à envoyer pour exercer la capacité du terminal $cap, c'est-à-dire pour exécuter sa $capcommande. Voir man 5 terminfo(sous Linux, le numéro de section peut varier sur d'autres unités) pour plus d'informations.

La séquence d'actions est la suivante: déplacer le curseur d'une ligne vers le bas ( cud1), puis vers le haut ( cuu1); enregistrer la position du curseur ( sc); déplacez le curseur d'une ligne vers le bas; imprimer [some status]; restaurer la position du curseur. Le bit de bas en haut au début n'est nécessaire que si l'invite se trouve sur la dernière ligne de l'écran. La ligne preexec efface la deuxième ligne ( el) afin qu'elle ne soit pas mélangée avec la sortie de la commande.

Si le texte de la deuxième ligne est plus large que le terminal, l'affichage peut être tronqué. Utilisez Ctrl+ Ldans une pincée pour réparer.

Gilles 'SO- arrête d'être méchant'
la source
5

Voici un bashéquivalent de la solution zsh de Gilles. Bash n'a pas de module terminfo natif, mais la tputcommande (fournie avec terminfo) fait à peu près la même chose.

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

Si le terminal ne prend pas en charge l'une des capacités, il reviendra à une invite sur une ligne.

La trapligne est un moyen hacky d'émuler la preexecfonction de zsh . Voir /superuser/175799/ pour plus d'informations.

EDIT : Script amélioré basé sur les commentaires de Gilles.

Jander
la source
@Gilles: Merci pour la contribution! Je pense que ça fonctionne mieux maintenant. J'ai essayé bash 4.1.5 dans gnome-terminal et xterm, et bash 3.2.48 dans OSX Terminal.
Jander