Was ist los mit `find-file-noselect`?

11

In einer kürzlichen Antwort von lunaryorn erklärte er:

Ich würde jedoch aus den bereits in den Kommentaren genannten Gründen gegen die meisten anderen Teile von Org empfehlen: Es ist alt und voller alter und schädlicher Praktiken (z. B. find-file-noselect, um Dateien nicht interaktiv zu lesen).

Kann jemand erklären, warum es find-file-noselecteine schlechte Idee ist, Dateien in Elisp-Programmen zu lesen? Gibt es einen besseren Weg? Ich frage, weil ich darüber nachgedacht habe, es in einem meiner Projekte zu verwenden.

mbork
quelle
Scheinbar gab es good-practicesvorher kein Etikett; Ist es eine gute Idee, es zu benutzen?
mbork
Ich denke, das good-practiceswürde unter die Kategorie "Meta-Tag" fallen, die von SE verpönt wird .
Nispio
1
@nispio Ich denke, es ist ein gültiges Tag, aber wir können dies natürlich zum Meta bringen.
Malabarba
1
@nsipio: Ich habe diesen Artikel durchgesehen und bin nicht einverstanden. Aber nicht ich entscheide. ;-)
mbork

Antworten:

14

TL; DR : Wenn find-file-noselectSie keine Kontrolle darüber haben, was tatsächlich passiert, werden möglicherweise beliebige Nebenmodi im Puffer aktiviert, je nachdem, was der Benutzer in seinem Puffer aktiviert hat init.el. Auch die Bereinigung ist schwierig.

Verwenden Sie with-temp-bufferund insert-file-contentsstattdessen. Wenn Sie bestimmte Haupt- oder Nebenmodi im Puffer benötigen, aktivieren Sie diese explizit . Verwenden Sie with-temp-filestattdessen zum Schreiben von Dateien, mit denen Sie trotz des Namens in beliebige Dateien schreiben können.

Nebenwirkungen

find-file-noselecthat viele Nebenwirkungen, einschließlich

  • interaktiv Fragen stellen (das allein ist ein No-Go bei nicht interaktiver Verwendung),
  • automatisch den Ansichtsmodus für schreibgeschützte Dateien aktivieren,
  • sonst in den normalen Modus wechseln,
  • und rennen find-file-hook.

Normaler Modus selbst

  • wählt automatisch einen geeigneten Hauptmodus für den aktuellen Puffer aus,
  • führt alle entsprechenden Major- und Minor-Mode-Hooks aus,
  • und liest alle lokalen Variablen für den aktuellen Puffer, dh Dateivariablen und Verzeichnisvariablen, die wiederum interaktive Fragen zu unsicheren lokalen Variablen stellen können.

Da alle Hooks ausgeführt werden, erhalten Sie alle vom Benutzer aktivierten Nebenmodi und Hakenfunktioneninit.el , die alles verursachen können, von geringfügigen Unannehmlichkeiten (wenn unerwünschte Nebenmodi aktiviert sind) bis hin zu schwerwiegenden Problemen (wenn der Benutzer eine erwartete Hook-Funktion hinzugefügt hat) aus einem interaktiven Kontext aufgerufen werden).

Ein Beispiel finden Sie unter https://github.com/flycheck/flycheck/issues/366 . Die Verwendung von führte dazu, find-file-noselectdass eine Datendatei von Flycheck syntaktisch überprüft wurde. Da dies beim Herunterfahren von Emacs geschah, war keine Zeit für eine erneute ordnungsgemäße Bereinigung, sodass eine temporäre Datei zurückblieb.

Aufräumen

Mit müssen find-file-noselectSie besonders vorsichtig sein, um den Puffer wieder zu töten. find-file-noselecttut das nicht für dich.

Sie müssen sich an einer Stelle an den Puffer erinnern und ihn sorgfältig verwenden unwind-protect, um sicherzustellen, dass der Puffer auch bei nicht lokalen Exits getötet wird.

Alternativen

Verwenden Sie zum Lesen von Dateien with-temp-bufferund insert-file-contents, das nur die grundlegendsten Aufgaben ausführt, z. B. die Konvertierung des Codierungssystems, aber keine Fragen stellt, Hooks aktiviert oder lokale Variablen einrichtet:

(with-temp-buffer
  (insert-file-contents (locate-user-emacs-file "foo.el"))
  ;; Enter the major mode explicitly
  (emacs-lisp-mode)
  ;; …
  )

with-temp-buffer achtet darauf, den temporären Puffer am Ende seines Körpers richtig abzutöten.

Verwenden Sie zum Schreiben von Dateien Folgendes, um with-temp-fileeinen temporären Puffer zu erstellen und den Inhalt in den angegebenen Dateinamen am Ende seines Körpers zu schreiben :

(with-temp-file  (locate-user-emacs-file "foo.el")
  (prin1 (list 'my 'data) (current-buffer)))
Mondhorn
quelle
10

Aus Abschnitt 24.3 im Elisp-Handbuch:

Verwenden Sie die Funktion, um den Inhalt einer Datei in einen Puffer zu kopieren insert-file-contents. (Verwenden Sie den Befehl nicht insert-filein einem Lisp-Programm, da dies die Marke setzt.)

Das Durchsuchen der Elisp-Dokumentation find-file-noselectist offensichtlich, dass es viel mehr als nur das Einlesen einer Datei in einen Puffer bewirkt. Vielleicht denken Leute, die diese Funktion für eine schlechte Idee halten, über die möglicherweise unerwünschten Nebenwirkungen nach? Ich denke, es hängt davon ab, was Sie erreichen wollen. Wenn Sie so sauberen / unberührten Pufferinhalt wie möglich haben möchten, ist es möglicherweise eine gute Idee, die alte und vertrauenswürdige with-temp-buffer+ insert-file-contentsKombination zu verwenden. Wenn Sie möchten, dass der Pufferinhalt dem find-fileProdukt so nahe kommt, möchten Sie ihn vielleicht verwenden find-file-noselect? Oder vielleicht hat er darüber nachgedacht find-file;)

Mathias Dahl
quelle
3
Wenn etwas nicht interaktiv gemacht wird, kann ich kein Szenario sehen, in dem Sie möchten, dass "der Pufferinhalt nahe an dem liegt, was die Find-Datei erzeugen würde" . find-file ist langsam, weil es eine Menge unnötiger Dinge erledigt, einschließlich aller Arten von Hooks. Die einzige "Funktion" der Suchdatei, die Sie möglicherweise möchten, ist der Hauptmodus, aber dann sollten Sie ihn einfach selbst aktivieren (Sie können nicht einmal garantieren, dass die Suchdatei den gewünschten Modus aktiviert).
Malabarba
Malabarba: Wenn Sie beabsichtigen, dass der Puffer für die Bearbeitung durch den Benutzer verfügbar bleibt, möchten Sie möglicherweise den find-fileProzess nachahmen .
Phils