Wie verhindert man eine Verlangsamung, wenn ein minderwertiger Prozess lange Schlangen erzeugt?


14

Ich benutze Emacs mit Geiser, um einen Schema-Code zu hacken. Während ich in der REPL herumspiele, bewerte ich manchmal Ausdrücke, die zu viel Ausgabe führen, oft alle in einer Zeile.

Ich habe zum Beispiel gerade mit SRFI-41 (Streams) gespielt und einen Charakter-Stream aus einer großen Datei erstellt. dann habe ich den stream gezwungen und geiser hat den gesamten inhalt der datei als zeichenstream in meinen puffer gepuffert. Fast sofort blieb Emacs stehen, als immer mehr Zeichen an die Ausgabezeile angehängt wurden und egal wie lange ich gedrückt hielt C-goder C-c C-cich Emacs (oder Geiser) nicht zum Stoppen bringen konnte.

Dies hat meine gesamte Emacs-Sitzung unterbrochen, da Emacs meine Eingaben jetzt völlig ignoriert und der Ansicht ist, dass es vorrangig sein muss, diesen massiven Zeichenstrom in einer Zeile in einen nicht reagierenden Geiser REPL-Puffer zu drucken.

Kann ich etwas tun, um meine Emacs-Sitzung vor meiner zerstörerischen Neugier zu schützen? (Warum wird Emacs so langsam, wenn sehr lange Zeilen angezeigt werden?) Kann ich ein Limit für lange Zeilen festlegen und Emacs mitteilen, dass es in Ordnung ist, einfach nicht zu versuchen, sehr lange Zeilen anzuzeigen?



2
In meiner Frage geht es nicht darum, lange Zeilen per se anzuzeigen. Ich möchte wissen, wie ich diese Art von Dingen überhaupt vermeiden kann (Emacs liest die Zeile aus einem minderwertigen Prozess, nicht aus einer Datei, die ich reparieren konnte). und es geht darum, wie ich verhindern kann, dass meine Emacs-Sitzung aufgrund von Emacs 'Engagement für einen einzelnen dynamischen Puffer verloren geht.
Rekado

"Nun, bei meiner Frage geht es nicht darum, lange Zeilen anzuzeigen." Dann sollten Sie vielleicht Ihren Titel ändern. Vielleicht möchten Sie die minderwertige Prozessausgabe filtern und nach einer bestimmten Anzahl von Zeichen eine neue Zeile hinzufügen?
Kindermädchen

Wirklich, das hat wenig mit langen Schlangen zu tun. yesin einem hat ansi-termzum Beispiel einen ähnlichen (aber nicht so schrecklichen) Effekt. Es ist wirklich nur die Textmenge, die Emacs zum Innehalten bringt.
PythonNut

Das Einfügen von Text in einen Puffer ist ziemlich schnell. Durch die Neuanzeige wird der Text langsamer angezeigt, als er tatsächlich ist. Um ehrlich zu sein, werden bei der Ausführung yesin einem VTE-Terminalemulator alle CPU-Kerne ausgelastet, sodass ich es nicht als Beispiel verwenden würde.
Wasamasa

Antworten:


12

Wie bereits in den Kommentaren beantwortet, ist es ein bekanntes Problem , dass Emacs bei langen Warteschlangen nur sehr langsam wieder angezeigt wird . Es wäre sehr schön, es zu reparieren, aber es sind viele Überlegungen erforderlich, um es richtig abzunehmen. Ich habe eine Vorstellung davon, wie dies auf der Grundlage von Abschnitt 6.3 dieses Dokuments erreicht werden könnte (im Grunde genommen speichere visuelle Zeileninformationen im aktuellen Puffer und aktualisiere sie beim Einfügen von Leerzeichen, Anzeigeeigenschaften, Fensteränderungen usw. und verwende diese Informationen dann in den Redisplay-Code, um nicht ständig danach zu suchen), aber ich kenne die C-Interna nicht gut genug, um ihn abzurufen.

Es gibt jedoch Problemumgehungen. Die naheliegendsten sind das Optimieren von anzeigebezogenen Parametern (z. B. das Aktivieren der visuellen Linienabschneidung in der grafischen Emacs-Instanz, das automatische Deaktivieren von Bidi-Funktionen in einem nicht grafischen Emacs usw.) und das Vorverarbeiten des Dateiinhalts, den Sie verwenden. Einlesen. Weniger offensichtlich ist, dass die Dateien automatisch nachbearbeitet werden, indem die Zeilen tatsächlich abgeschnitten werden oder indem Texteigenschaften hinzugefügt werden, die die Zeilen kürzer erscheinen lassen, als sie tatsächlich sind. Um dies in eine interessantere Antwort zu verwandeln, comintstelle ich einen ziemlich hässlichen Hack der vorherigen Option vor, der nur für abgeleitete Modi funktioniert:

(defun my-comint-shorten-long-lines (text)
  (let* ((regexp "^\\(.\\{80\\}\\).*?$")
         (shortened-text (replace-regexp-in-string regexp "\\1" text)))
    (if (string= shortened-text text)
        text
      (propertize shortened-text 'help-echo text))))

(add-hook 'comint-preoutput-filter-functions 'my-comint-shorten-long-lines)

Dies definiert my-comint-shorten-long-lineseine Funktion, die einen möglicherweise aus vielen Zeilen bestehenden String verwendet und mithilfe regulärer Ausdrücke eine Zeile mit einer Länge von 80 Zeichen oder mehr durch eine verkürzte Version ersetzt, die den Originaltext anzeigt, wenn Sie den Mauszeiger darüber halten. Bei Verwendung als Hook-In comint-preoutput-filter-functionswerden alle comintAusgaben gefiltert, bevor sie angezeigt werden.

Diese Wiedergabe des Hack hat jedoch eine ziemlich ernsthafte Schwäche. In Modi, in denen grundlegende Schriftarten verwendet werden (wie z. B. M-x ielm), werden Zeilen, die Teil einer Zeichenfolge sind, abgeschnitten, und auf diese Weise wird alles bis zum nächsten Anführungszeichen als Zeichenfolge fontifiziert! Das ist nicht das, was wir wollen und es kann mit etwas mehr Regex-Beherrschung behoben werden (wird aber vermutlich in einer REPL für eine Sprache wie Python brechen). Lassen Sie uns auch die verkürzte Ausgabe hervorheben:

(defun my-comint-shorten-long-lines (text)
  (let* ((regexp "^\\(.\\{80\\}\\).*?\\(\"?\\)$")
         (shortened-text (replace-regexp-in-string regexp "\\1\\2" text)))
    (if (string= shortened-text text)
        text
      (propertize shortened-text 'font-lock-face 'shadow 'help-echo text))))

(add-hook 'comint-preoutput-filter-functions 'my-comint-shorten-long-lines)

Das ist ein bisschen besser, aber immer noch hässlich. Das Schweben auf der Ausgabe von so etwas wie find /in M-x shellist nicht ansprechend (im Idealfall möchten wir nur die unverkürzte Zeile anzeigen, nicht die gesamte Ausgabe), die Zeichenfolgenerkennung ist bestenfalls rudimentär und das Abschneiden könnte besser mit Ellipsen angezeigt werden, anstatt alles zu beschriften. Darüber hinaus kann nicht garantiert werden, dass der eingehende Text nicht in Stapel umgewandelt wird. All dies schreit nach dem Ausführen des Verarbeitungsschritts in einem temporären Puffer, wird jedoch dem Leser als Übung (oder dem Autor als möglicher Blog-Beitrag) überlassen.


4

Wie dies auch bei Python der Fall ist , besteht die Lösung bei python-mode.el, https://launchpad.net/python-mode , darin, eine direkte Verbindung zum Prozess herzustellen, nicht über den Comint-Modus.

Verlässt sich auf start-processund verarbeitet den Sende-String

Zum Beispiel siehe Funktionen py--start-fast-processundpy--fast-send-string-intern

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.