Wie starte ich XTerm mit der Eingabeaufforderung unten?

12

Beim Starten von XTerm beginnt die Eingabeaufforderung in der ersten Zeile des Terminals. Beim Ausführen von Befehlen bewegt sich die Eingabeaufforderung nach unten, bis sie den Boden erreicht, und bleibt von da an dort (nicht einmal Shift- Page Downoder die Maus kann dies ändern). Anstatt dass der Beginn der Terminallebensdauer "speziell" ist, sollte sich die Eingabeaufforderung immer am unteren Rand des Terminals befinden. Bitte beachten Sie, dass ich eine mehrzeilige Eingabeaufforderung habe .

Natürlich sollte es ansonsten wie zuvor funktionieren (veränderbar, scrollbar, keine unnötigen Zeilenumbrüche in der Ausgabe und keine Ausgabe, die auf mysteriöse Weise verschwindet), daher PROMPT_COMMAND='echo;echo;...'ist eine ähnliche Option nicht möglich. Die Lösung sollte idealerweise nicht schalenspezifisch sein.

Bearbeiten: Die aktuelle Lösung weist in einfachen Fällen einige Probleme auf:

  • Es ist Bash-spezifisch . Eine ideale Lösung sollte auf andere Schalen tragbar sein.
  • Es schlägt fehl, wenn andere Prozesse geändert werdenPS1 . Ein Beispiel dafür ist virtualenv, das fügt (virtualenv)am Anfang der PS1, die dann immer nur über die Klappe verschwindet.
  • Ctrl- Entferntl jetzt die letzte Seite des Verlaufs.

Gibt es eine Möglichkeit, diese Probleme zu vermeiden, ohne XTerm zu verzweigen?

l0b0
quelle
Irgendwie müssen wir leere Zeichen in den Bildlaufleistenpuffer von Xterm einfügen.
SHW
3
Tatsächlich kann die Eingabeaufforderung jederzeit durch Ausführen des clearBefehls einfach wieder nach oben verschoben werden .
Werediver
@ SHW Ich hatte gehofft, dass es dafür eher eine Einstellung als einen Hack gibt. Terminal-Hacks neigen meiner Erfahrung nach dazu, sehr subtile Fehler einzuführen.
10b0
@werediver Aber ich möchte nie, dass es oben ist.
10b0
1
Da nur die Shell weiß, wann sie eine Eingabeaufforderung ausgibt, muss sich jede Lösung im Kontext der Shell befinden. Selbst das Verzweigen von XTerm hilft nicht weiter, da XTerm nicht weiß, ob es sich bei der Ausgabe um eine Eingabeaufforderung handelt oder nicht. Für das Terminal ist die Shell-Eingabeaufforderung nur eine andere Zeichenfolge, die sich von keiner anderen Zeichenfolge unterscheidet, die sie möglicherweise empfängt.
Celtschk

Antworten:

11

Wenn Sie verwenden bash, sollte Folgendes den Trick tun:

TOLASTLINE=$(tput cup "$LINES")
PS1="\[$TOLASTLINE\]$PS1"

Oder (weniger effizient, da tputvor jeder Eingabeaufforderung ein Befehl ausgeführt wird, die Größe des Terminalfensters jedoch geändert wird):

PS1='\[$(tput cup "$LINES")\]'$PS1

Um zu verhindern, tputdass der Exit-Code geändert wird, können Sie ihn explizit speichern und zurücksetzen:

PS1='\[$(retval=$?;tput cup "$LINES";exit $retval)\]'$PS1

Beachten Sie, dass die Variable retvallokal ist. Es wirkt sich nicht auf eine retvalVariable aus, die Sie möglicherweise anders in der Shell definiert haben.

Da die meisten Terminals cupgleich sind \e[y;xH, können Sie sie auch fest codieren:

PS1='\[\e[$LINES;1H\]'$PS1

Wenn Sie möchten, dass PS1 später nicht zurückgesetzt wird, können Sie auch die PROMPT_COMMANDVariable verwenden. Wenn festgelegt, wird es als Befehl ausgeführt, bevor die Eingabeaufforderung ausgegeben wird. So kann der Effekt auch durch erreicht werden

PROMPT_COMMAND='(retval=$?;tput cup "$LINES";exit $retval)'

Während das Zurücksetzen dies PS1nicht beeinflusst, kann sich natürlich auch eine andere Software ändern PROMPT_COMMAND.

Celtschk
quelle
Wie tputunterscheiden sich viele echoBefehle? (Aus Neugier fragen)
SHW
@ l0b0, verdient wahrscheinlich keine separate Antwort. Ich hoffe, Celtschk macht es nichts aus, dass ich seine / ihre Antwort bearbeitet habe.
Stéphane Chazelas
'\[$(tput cup "$LINES")\]' funktioniert wunderbar . Vielen Dank!
10.
Es gibt ein Problem mit tput: Es scheint zurückgesetzt zu werden $exit_code. Behoben durch Verwenden von \[\e[$LINES;1H\].
10b0
1
@ l0b0: Ich habe jetzt eine Version hinzugefügt tput, die den Exit-Code beibehält .
Celtschk
4

Als leichte Vereinfachung der vorherigen Antwort fiel es mir leichter, einfach zu laufen:

tput cup $LINES

am Anfang von .bashrcoder .zshrc. Es macht einfach den Job.

Vorteile:

  • Es wird nur einmal gedruckt, wenn Sie Ihre Shell starten

Nachteile:

  • wenn Bildschirm mit ^ L löscht, ist es nicht drucken und Aliasing clearzu clear; tput ...nicht hilft;
  • Die Eingabeaufforderung wird an eine andere Stelle verschoben, wenn die Größe des Terminals geändert wird
phil pirozhkov
quelle
2

Die Antworten mit $LINESsind unnötig nicht portierbar. Wie in ausgeführt resize, können Sie einfach darum bitten xterm, die Position auf eine beliebig große Zeilennummer einzustellen, z.

tput cup 9999 0

(Angenommen, Sie haben ein Fenster mit weniger als 10.000 Zeilen, ohne Rückblick ).

Da sich die Zeichenfolge nicht als Nebeneffekt beim Ändern der Fenstergröße ändert, können Sie diese einmal berechnen und als Konstante in Ihre Eingabeaufforderungszeichenfolge einfügen, z.

TPUT_END=$(tput cup 9999 0)

und später

PS1="${TPUT_END} myprompt: "

nach Ihren Wünschen.

Wie bei anderen Prozessen PS1, die geändert werden: Sie müssen PS1nach diesen Änderungen neu berechnen , um sicherzustellen, dass es so aussieht, wie Sie es möchten. Die Frage enthält jedoch nicht genügend Details, um darauf hinzuweisen, wo die Änderungen vorgenommen werden müssen.

Und schließlich: Das Verhalten bei der Tab-Vervollständigung passt aufgrund der Annahmen von bash nicht zu dieser Art von Änderung.

Thomas Dickey
quelle
Was meinen Sie mit "das Verhalten bei der Tab-Vervollständigung passt nicht zu dieser Art von Änderung"?
10.08.
Ich denke du meinst PS1="${TPUT_END} myprompt: ", oder sogarPS1="${TPUT_END}${PS1}"
l0b0
Für letztere - richtig (Tippfehler beim Denken an Makefiles). Bei ersteren denke ich daran, dass die Befehlsbearbeitung von bash davon abhängt, dass die Zeile (mit Eingabeaufforderung) erneut gedruckt werden kann, und dass Sie aufgrund der Befehlsvervollständigung ein merkwürdiges Verhalten erhalten können, wenn dies mit dem Scrollen kombiniert wird.
Thomas Dickey