Gibt es einen Befehl, damit bash eine neue Eingabeaufforderungszeichenfolge druckt und die aktuelle Zeile neu zeichnet?

367
Ari Sweedler

Anstatt auf langsame Befehle zu warten, möchte ich sie im Hintergrund ausführen. Wenn sie jedoch fertig sind und nach stdout drucken, erhalte ich (wo mein Cursor steht) Folgendes:

$ slowcmd & $ cmd_output █ 
  • Vor meinem Cursor befindet sich keine Eingabeaufforderung.
  • und slowcmdkann ein beliebiger langsamer Befehl sein (für das, was ich versucht habe, sagte ich gerade alias slowcmd='sleep 1 && echo cmd_output')

Wobei mir so etwas gefallen würde:

$ slowcmd && redrawPromptString & $ cmd_output $ █ 

Wo nach der Ausgabe des Befehls wird ein neuer Prompt String für mich ausgedruckt.

Was kann ich tun, um das zu redrawPromptStringtun, was ich will? Ich habe versucht clear, kill $$eine ^Can das Terminal zu schicken, und schließlich printf "^C"(natürlich hat das nicht funktioniert). Ich laufe Bash. (GNU bash, Version 3.2.57).

1
Wie wäre es mit `redrawPromptString`?` Printf '$' `? dsstorefile1 vor 5 Jahren 0
Mein PS1 ist farbig und verwendet Sonderzeichen mit Backslash - wie zum Beispiel `\ @`. (Aber ja, das ist eine geeignete Lösung für alle vernünftigen Personen, die nicht genau wissen wollen, was sie wollen ...) Ahaha, aber ich hasse es, aus Unwissenheit tun zu können, was ich will! Aus Mangel an Unterstützung in dem Programm, das ich verwende? Sicher (vorerst). Aber aus Unwissenheit? Das gefällt mir nicht Ich werde google und stack overflow und frage jeden, den ich jetzt vielleicht denke, bis die Kühe nach Hause kommen. Ari Sweedler vor 5 Jahren 0
Warum nicht ein separates, dediziertes Terminal für `slowcmd` verwenden? Verwenden Sie einen Terminalmultiplexer wie "tmux", erstellen Sie ein neues Fenster und führen Sie dort "slowcmd" aus, während Sie wieder zum funktionierenden Terminal wechseln und Ihre Arbeit fortsetzen können. Alex vor 5 Jahren 1
@Alex Ich kann auch eine neue Registerkarte in iTerm öffnen. Ich frage nicht, wie ich die Kontrolle über mein Terminal übernehmen kann, während ich einige Befehle benutze, die einige Zeit in Anspruch nehmen, weil ich bereits weiß, wie das geht. Und wenn ich so eine Frage stellte, wurde ich zu Recht herabgestuft. Nein, ich suche keine Heuristik, ich suche eine Lösung Ari Sweedler vor 5 Jahren 0

2 Antworten auf die Frage

1
RalfFriedl

Wenn Sie drücken Ctrl+L, macht es teilweise, was Sie wollen. Die aktuelle Zeile wird neu gezeichnet, einschließlich aller Eingaben, die Sie bis zu diesem Punkt eingegeben haben, einschließlich der Cursorposition. Der Bildschirm wird jedoch gelöscht, sodass Ihre vorherige Ausgabe verloren geht (oder bei einem Terminalfenster im Scrollback-Puffer). Auf der anderen Seite waren Sie bereit zu versuchen clear, also ist das vielleicht kein Problem.

Ja, "clear" und "^ L" tun nicht was ich will. Ich möchte, dass der Befehl zum Fertigstellen eine neue Eingabeaufforderung erstellt, sodass ich nichts manuell tun muss. Es muss einen Weg geben! Ich habe `^ C` oder` ^ L` oder einfach nur `verwendetAlle arbeiten _. Aber ich mache eine suboptimale Sache aus Unwissenheit, und ich hasse das! Ari Sweedler vor 5 Jahren 0
Sie erhalten keine neue Aufforderung, da die Aufforderung bereits gedruckt wurde. Sie können jedoch 'set -b' verwenden, damit die Shell sofort die [1] + Done-Taste druckt und sich der Cursor in einer neuen Zeile befindet. Sie können die "SIGCHLD" auch "fangen" und verwenden, um eine neue Eingabeaufforderung zu drucken, aber Sie müssen herausfinden, ob der Hintergrundprozess beendet wurde. RalfFriedl vor 5 Jahren 1
1
Kamil Maciorowski

Verwenden Sie die eingebaute redraw-current-lineFunktion bind. Zuerst prüfen, ob es vielleicht schon gebunden ist:

bind -q redraw-current-line 

Ich habe es noch nie standardmäßig gesehen, daher müssen Sie es wahrscheinlich binden. Wählen Sie eine Tastenkombination aus, sagen wir Ctrl+ Y. Prüfen Sie, ob es bereits vergeben ist:

bind -p | grep -F '"\C-y' 

Leere Ausgabe bedeutet, dass die Kombination nicht verwendet wird. Wenn ja, lass uns daran binden redraw-current-line:

bind "\C-y":redraw-current-line 

Wenn jetzt ein Hintergrundprozess Ihre Befehlszeile durcheinander bringt, drücken Sie Ctrl+ Y. Dann wird Ihre Eingabeaufforderung zusammen mit dem Befehl, den Sie nur teilweise eingegeben haben (falls vorhanden), neu gezeichnet, sodass Sie fortfahren können, als ob nichts passiert wäre.

Um die Bindung dauerhaft zu machen, können Sie den obigen Befehl zu Ihrem Befehl hinzufügen ~/.bashrc, aber nicht. Der richtige Ansatz ist zu ändern ~/.inputrc(für Benutzer) oder /etc/inputrc(systemweit). Auf diese Weise readline(3)gehorcht jedes Programm, das eine Bibliothek verwendet . Die Zeile, die zu einer Datei hinzugefügt werden soll, sieht folgendermaßen aus:

"\C-y":redraw-current-line 

Wenn Sie jedoch ~/.inputrcneu erstellen, vergewissern Sie sich, dass in der ersten Zeile Folgendes angezeigt wird $include /etc/inputrc. Dies liegt daran, dass dies bis zu diesem Zeitpunkt readlineverwendet wurde /etc/inputrcund Ihr Workflow möglicherweise auf den Inhalt dieser Datei angewiesen ist. Von jetzt an verwendet die Bibliothek ~/.inputrcstattdessen Ihre . Die Zeile $include /etc/inputrcbewirkt, dass die systemweite Datei ebenfalls analysiert wird.

Weitere Informationen finden Sie unter help bindund man 3 readline.

Ich habe "\ Cc" verwendet, das ein "INTR-Zeichen" gemäß "stty" sendet und bewirkt, dass alle Eingaben verworfen werden und das Eingabeaufforderungsskript erneut präsentiert wird. Aber "Redraw-Current-Line" ist genau das, wonach ich gesucht habe! Es verliert nicht meine aktuelle Eingabe ODER Bildschirmhistorie. Ich will nicht gierig sein, aber kennen Sie einen CLI-Befehl, der eine Readline-Funktion auslösen kann? Ari Sweedler vor 5 Jahren 0
+1 für die ausführliche Erklärung zu 'bind'. Es ist sehr schwer, eine gute Dokumentation darüber zu finden. Man Bash hat gute Sachen unter Shell Builtin Commands (wenn Sie es durch die ganze Scheiße finden können). Für alle, die noch lesen, handelt es sich bei diesem [link] (https://www.computerhope.com/unix/bash/bind.htm) nur um `bind`, und ich fand es viel noob-freundlicher. Ari Sweedler vor 5 Jahren 0