Jak sprawdzić, czy bufor odwiedza plik?

9

Chciałbym sprawdzić, czy jakiś (powiedzmy, bieżący) bufor odwiedza plik, czy nie. Mógłbym powiedzieć:

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

ale wydaje się, że nie jest zbyt elegancki - interesuje mnie tylko wartość logiczna, a nie faktyczna nazwa bufora. Gdyby buffer-file-namefunkcja została napisana w Elisp, mógłbym zajrzeć do jej źródła, aby dowiedzieć się, z czego korzysta - ale jest napisane w C i chociaż mogę zainstalować źródła Emacsa, obawiam się, że nie znalazłbym nazwy elisp dla funkcji, która i tak sprawdza to, co tam mam.

Potrzebuję do tego, aby utworzyć katalog na podstawie nazwy bieżącego bufora, a obecnie robię mniej więcej to:

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

Więc jaki byłby Elisp-idiomatyczny sposób na zrobienie tego?

Mbork
źródło
2
Nie wiem, dlaczego tak buffer-file-namenaprawdę sprzeciwisz się używaniu , jest to właściwy sposób (jeśli naprawdę chcesz t, zrób to, (and (buffer-file-name) t)ale jest to brzydsze IMO). Jego implementacją jest odczytywanie filenamepola struktury bufora C, która i tak nie jest dostępna bezpośrednio z Elisp. Ostatecznie jest to po prostu wskaźnik zerowy lub nie.
Sigma,
Cóż, jeśli to właściwy sposób, nie mam nic przeciwko. Jak powiedziałem - nie znałem implementacji języka C, a zdrowy rozsądek mówi, że pytanie o nazwę pliku, gdy chcę tylko wiedzieć, czy istnieje jakakolwiek, może być zbędne.
mbork,
I zgadzam się, że (and (buffer-file-name) t)wygląda to dziwnie.
mbork,
Jeśli uważasz, że (if (buffer-file-name) ... )to nie jest eleganckie, to nie pisałeś długo w elisp. Staje się coraz bardziej brzydki.
nispio

Odpowiedzi:

12

Argumentowałbym, że twoje użycie jest idiomatyczne, ponieważ nazwa bufora jest sama w sobie całkowicie odpowiednią wartością logiczną. Cytowanie z instrukcji :

Test prawdy ma ważny aspekt w wyrażeniu if. Do tej pory mówiliśmy o „prawdzie” i „fałszu” jako o wartościach predykatów, jakby były nowymi rodzajami obiektów Lisp Emacsa. W rzeczywistości „fałsz” to tylko nasz stary przyjaciel nil. Wszystko inne - w ogóle - jest „prawdziwe”.

Aby przejść dalej, sprawdź kod dla clone-buffer. Oczekuję, że zobaczysz:

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

Zauważ, że jest to testowanie wiązania zmiennej buffer-file-namezamiast wywoływania funkcji bez argumentu (buffer-file-name), ale oba powinny zawsze zachowywać się tak samo.

strzałki fioletowe
źródło
8

Możesz użyć (buffer-file-name)(z opcjonalnym argumentem bufora) lub buffer-file-namezmiennej lokalnej bufora . Oba obliczają tę samą wartość dla danego bufora.

Jest to jednak idiomatyczny sposób na wykonanie tego w Elisp, więc twój kod jest w porządku. Jeśli desperacko tego chciałeś, zawsze możesz wykonać funkcję buffer-has-file-potoki.

phils
źródło
Dzięki. Czy jest jakaś znacząca różnica w wyborze funkcji lub zmiennej?
mbork
1
Nie wydaje mi się Jeśli musisz wskazać argument bufora, (buffer-file-name BUFFER)to z pewnością jest on ładniejszy niż (with-current-buffer BUFFER buffer-file-name), ale poza tym nie sądzę, że ma to znaczenie, którego używasz (a ponieważ funkcja jest napisana w C, wątpię, żeby była nawet duża różnica w wydajności).
phils
3

Po prostu użyj buffer-file-name. W Lisp często używamy nie- nilwartości, aby oznaczać „ prawda” .

Jedynym czasem, kiedy możesz tego uniknąć, jest to, że funkcja jest kosztowna lub ma niepożądane skutki uboczne.

Rysował
źródło
Widzę. Wiem, że wszystko, co nie niljest prawdą, pomyślałem o tym, kiedy chcę tylko wiedzieć, czy jakieś imię istnieje, jest „kosztowne” - ale najwyraźniej tak nie jest.
mbork,
1

Z rozdziału „Lista buforów” dokumentacji:

Lista zwrócona przez listę buforów jest konstruowana specjalnie; nie jest to wewnętrzna struktura danych Emacsa , a jej modyfikacja nie ma wpływu na kolejność buforów.

Musisz więc znaleźć sposób wyszukiwania na liście buforów na żywo. Tutaj jest jeden:

  (if (string-match-p (regexp-quote "My buffer name") (format "%s" (buffer-list)))
      (message "Open")
    (message "Not open"))
yPhil
źródło