Wie überprüfe ich, ob ein Puffer eine Datei besucht?

9

Ich möchte überprüfen, ob ein (z. B. aktueller) Puffer eine Datei besucht oder nicht. Ich könnte sagen:

(if (buffer-file-name) ...)

aber es scheint nicht sehr elegant zu sein - was mich interessiert, ist nur der boolesche Wert, nicht der tatsächliche Name des fraglichen Puffers. Wenn die buffer-file-nameFunktion in Elisp geschrieben wäre, könnte ich in ihrer Quelle nachsehen, was sie verwendet - aber sie ist in C geschrieben, und während ich die Emacs-Quellen installieren könnte, befürchte ich, dass ich keinen Elisp-Namen finden würde für die Funktion, die prüft, was ich dort sowieso bin.

Wofür ich es brauche, möchte ich ein Verzeichnis erstellen, das auf dem Namen der Datei des aktuellen Puffers basiert, und derzeit mache ich mehr oder weniger Folgendes:

(make-directory (if (buffer-file-name) (file-name-base) "default-dir"))

Also, was wäre die Elisp-idiomatische Art, dies zu tun?

mbork
quelle
2
Ich buffer-file-namebin mir nicht sicher, warum Sie die Verwendung wirklich ablehnen, es ist der richtige Weg, dies zu tun (wenn Sie es wirklich wirklich wollen t, tun Sie es, (and (buffer-file-name) t)aber das ist hässlicher, IMO). Seine Implementierung liest das filenameFeld der Puffer-C-Struktur, auf die ohnehin nicht direkt von Elisp aus zugegriffen werden kann. Am Ende ist es nur ein Zeiger, der entweder null ist oder nicht.
Sigma
Nun, wenn das der richtige Weg ist, ist das in Ordnung für mich. Wie gesagt - ich kannte die C-Implementierung nicht und der gesunde Menschenverstand sagt, dass das Nachfragen nach dem Dateinamen, wenn ich nur wissen möchte, ob es einen gibt, möglicherweise redundant ist.
mbork
Und ich stimme zu, das (and (buffer-file-name) t)sieht seltsam aus.
mbork
Wenn Sie das nicht für (if (buffer-file-name) ... )elegant halten, haben Sie nicht lange in elisp programmiert. Ab hier wird es nur noch hässlicher.
Nispio

Antworten:

12

Ich würde argumentieren, dass Ihre Verwendung ein idiomatisches Elisp ist, da der Name des Puffers ein vollkommen geeigneter boolescher Wert für sich ist. Zitat aus dem Handbuch :

Der Wahrheitstest in einem if-Ausdruck hat einen wichtigen Aspekt. Bisher haben wir von "wahr" und "falsch" als Werten von Prädikaten gesprochen, als wären sie neue Arten von Emacs Lisp-Objekten. In der Tat ist "falsch" nur unser alter Freund nil. Alles andere - überhaupt nichts - ist "wahr".

Überprüfen Sie den Code für clone-buffer. Ich gehe davon aus, dass Sie Folgendes sehen werden:

(interactive
 (progn
   (if buffer-file-name
       (error "Cannot clone a file-visiting buffer"))
...

Beachten Sie, dass hiermit die Variablenbindung von getestet wird, buffer-file-nameanstatt die Funktion ohne Argument aufzurufen. (buffer-file-name)Die beiden sollten sich jedoch immer gleich verhalten.

lila_Pfeile
quelle
8

Sie können entweder (buffer-file-name)(mit optionalem Pufferargument) oder die buffer-file-nameVariable buffer-local verwenden . Beide werden für einen bestimmten Puffer auf den gleichen Wert ausgewertet.

Das ist der idiomatische Weg , dies in Elisp zu tun, obwohl, so dass Ihr Code ist in Ordnung. Wenn Sie es unbedingt wollten, können Sie jederzeit eine buffer-has-file-pWrapper-Funktion erstellen.

Phils
quelle
Vielen Dank. Gibt es einen signifikanten Unterschied bei der Auswahl der Funktion oder der Variablen?
mbork
1
Das glaube ich nicht. Wenn Sie das Pufferargument angeben müssen, (buffer-file-name BUFFER)ist es sicherlich besser als (with-current-buffer BUFFER buffer-file-name), aber ansonsten denke ich nicht, dass es wichtig ist, welches Sie verwenden (und da die Funktion in C geschrieben ist, bezweifle ich, dass es sogar einen großen Unterschied in der Leistung gibt).
Phils
3

Einfach benutzen buffer-file-name. In Lisp verwenden wir oft einen Nichtwert nil, um wahr zu bedeuten .

Möglicherweise möchten Sie dies nur vermeiden, wenn die Funktion teuer ist oder unerwünschte Nebenwirkungen aufweist.

Drew
quelle
Aha. Ich weiß, dass alles, was nicht nilwahr ist, ich dachte nur, den Namen zu greifen, wenn ich nur wissen will, ob ein Name existiert, ist "teuer" - aber anscheinend ist es nicht so.
mbork
1

Aus dem Kapitel "Pufferliste" der Dokumentation:

Die von der Pufferliste zurückgegebene Liste ist speziell erstellt. Es handelt sich nicht um eine interne Emacs-Datenstruktur , und ihre Änderung hat keine Auswirkungen auf die Reihenfolge der Puffer.

Sie müssen also einen Weg finden, um in der Liste der Live-Puffer zu suchen. Hier ist eine:

  (if (string-match-p (regexp-quote "My buffer name") (format "%s" (buffer-list)))
      (message "Open")
    (message "Not open"))
yPhil
quelle