¿Cómo verificar si un búfer está visitando un archivo?


9

Me gustaría comprobar si algún búfer (por ejemplo, actual) está visitando un archivo o no. Yo podría decir:

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

pero parece no ser muy elegante: lo que me interesa es solo el valor booleano, no el nombre real del búfer en cuestión. Si la buffer-file-namefunción se escribiera en Elisp, podría examinar su fuente para averiguar qué usa, pero está escrita en C, y aunque podría instalar las fuentes de Emacs, me temo que no encontraría un nombre elisp para la función que comprueba lo que busco allí de todos modos.

Lo que necesito es que quiero crear un directorio basado en el nombre del archivo del búfer actual, y actualmente estoy haciendo más o menos esto:

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

Entonces, ¿cuál sería la forma idiomática de Elisp de hacer esto?


2
No estoy seguro de por qué se opone a usar buffer-file-namerealmente, es la forma correcta de hacerlo (si realmente lo desea t, hágalo, (and (buffer-file-name) t)pero eso es más feo). Su implementación es leer el filenamecampo de la estructura del búfer C, que de todos modos no es accesible directamente desde Elisp. Al final, es solo un puntero que es nulo o no.
Sigma

Bueno, si este es el camino correcto, está bien para mí. Como dije, no conocía la implementación de C, y el sentido común dice que pedir el nombre de archivo cuando solo quiero saber si hay alguno podría ser redundante.
mbork

Y estoy de acuerdo en que se (and (buffer-file-name) t)ve extraño.
mbork

Si no crees que (if (buffer-file-name) ... )sea ​​elegante, entonces no has estado codificando en elisp por mucho tiempo. Solo se pone más feo desde aquí.
nispio

Respuestas:


12

Yo diría que su uso es elisp idiomático, ya que el nombre del búfer es un valor booleano perfectamente apropiado por derecho propio. Citando del manual :

Hay un aspecto importante en la prueba de verdad en una expresión if. Hasta ahora, hemos hablado de 'verdadero' y 'falso' como valores de predicados como si fueran nuevos tipos de objetos Emacs Lisp. De hecho, 'falso' es solo nuestro viejo amigo nil. Cualquier otra cosa, cualquier cosa, es "verdadera".

Para avanzar en el punto, consulte el código de clone-buffer. Espero que veas lo siguiente:

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

Tenga en cuenta que esto está probando el enlace variable de en buffer-file-namelugar de llamar a la función sin argumento (buffer-file-name), pero los dos siempre deben comportarse igual.


8

Puede usar ya sea (buffer-file-name)(con argumento de buffer opcional) o la buffer-file-namevariable local de buffer . Ambos evalúan al mismo valor para un búfer dado.

Sin embargo, esa es la forma idiomática de hacer esto en Elisp, por lo que su código está bien. Si quisieras desesperadamente, siempre podrías hacer que una buffer-has-file-penvoltura funcione.


Gracias. ¿Hay alguna diferencia significativa para elegir la función o la variable?
mbork

1
No lo creo. Si necesita indicar el argumento del búfer, entonces (buffer-file-name BUFFER)es ciertamente mejor (with-current-buffer BUFFER buffer-file-name), pero no creo que importe cuál use (y como la función está escrita en C, dudo que haya mucha diferencia en el rendimiento).
phils

3

Solo úsalo buffer-file-name. En Lisp a menudo usamos un no nilvalor para significar verdadero .

Las únicas veces que querrá evitar esto es si la función es costosa o tiene efectos secundarios no deseados.


Veo. Sé que todo lo que no niles cierto, pensé en tomar el nombre cuando solo quiero saber si existe algún nombre que sea "costoso", pero aparentemente no lo es.
mbork

1

Del capítulo "Lista de búfer" de la documentación:

La lista devuelta por buffer-list se construye específicamente; no es una estructura de datos interna de Emacs , y modificarla no tiene efecto en el orden de los buffers.

Por lo tanto, debe encontrar una manera de buscar en la lista de buffers en vivo. Aquí hay uno:

  (if (string-match-p (regexp-quote "My buffer name") (format "%s" (buffer-list)))
      (message "Open")
    (message "Not open"))
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.