La función para mostrar la ruta completa del archivo actual en mini búfer

98

Necesito obtener la ruta completa del archivo que estoy editando con emacs.

  • ¿Hay alguna función para eso?
  • Si no es así, ¿cuál sería la función elisp para conseguirlo?
  • ¿Cómo puedo copiar el resultado (nombre de la ruta) en un portapapeles para poder reutilizarlo?

Estoy usando Mac OS X y Aqumacs.

(setq filepath (get-fullpath-current-file)) ???
(copy-to-clipboard 'filepath) ???

ADICIONAL

(defun show-file-name ()
  "Muestra el nombre del archivo de ruta completo en el minibúfer".
  (interactivo)
  (mensaje (nombre-archivo-búfer))
  (kill-new (file-truename búfer-nombre-archivo))
)
(global-set-key "\ C-cz" 'show-file-name)

Combinando las dos respuestas que obtuve, podría obtener lo que quiero. Gracias por las respuestas. Y algunas preguntas más.

  • ¿Para qué sirve (file-truename)?
  • ¿Puedo copiar el nombre de la ruta en el portapapeles del sistema (SO), no en el kill ring, para poder usar la información con las otras aplicaciones?
prosseek
fuente

Respuestas:

91

Es la función incorporada buffer-file-nameque le brinda la ruta completa de su archivo.

Lo mejor que puede hacer es que la ventana de emacs muestre siempre el nombre de su sistema y la ruta completa del búfer que está editando actualmente:

(setq frame-title-format
      (list (format "%s %%S: %%j " (system-name))
        '(buffer-file-name "%f" (dired-directory dired-directory "%b"))))

También puedes hacer algo como esto:

(defun show-file-name ()
  "Show the full path file name in the minibuffer."
  (interactive)
  (message (buffer-file-name)))

(global-set-key [C-f1] 'show-file-name) ; Or any other key you want
Jérôme Radix
fuente
7
En emacs 24 buffer-file-namees una variable
barracel
5
... pero también sigue siendo una función
phils
16
Si es una función, ¿por qué no aparece M-x?
asmeurer
8
asmeurer - porque no es interactivo
Ben Fitzgerald
2
@Talespin_Kit Sí, absolutamente. Elisp es un "lisp-2" en lugar de un "lisp-1", lo que significa que hay dos espacios de nombres independientes (variables y funciones). Por tanto, cada símbolo tiene un "intervalo de función" y un "intervalo de valor", y el intervalo al que se accede depende del contexto. Hay muchos ejemplos en la práctica (por ejemplo, cualquier nombre de modo menor será tanto una función como una variable). Esta es también la razón por la que necesita usar los gustos de funcallpara llamar a una función que se almacena como el valor de una variable foo, porque si lo usa (foo), estaría usando la ranura de función de en foolugar de la ranura de valor.
phils
73

Para tomar prestado de la respuesta de Jérôme Radix, si solo desea ver rápidamente la ruta del archivo del búfer actual, puede hacerlo M-: buffer-file-name.

Alternativamente, escriba (buffer-file-name)en el búfer en algún lugar y ejecute C-x C-eel paréntesis de cierre (esto funcionará en cualquier modo, no solo en modo lisp).

como medidor
fuente
3
Gracias, pensé buffer-file-namecomo una función, pero no aparece M-x, pero aparece M-:como emacs eval, allí puedo ejecutar el comando, gracias a su respuesta :)
PeterZD
6
Sí, M-xsolo ejecuta funciones interactivas, mientras que M-:ejecuta cualquier función elisp.
asmeurer
40

Mi truco es hacer un me C-x C-fgusta para abrir un archivo, rellenará previamente el minibuff con la ruta del archivo actual, C-gpara salir. Más rápido que M-: buffer-file-namecualquier otro método, pero mucho más feo.

Julien Palard
fuente
Yo también hago esto. No es tan duro emacs-y, pero si lo único que me importa es la ruta al archivo actual, funciona.
andrunix
Si abre un archivo, diga A, y luego salta a otro archivo, diga B, por ejemplo, usando alguna funcionalidad de salto a la definición de un complemento, este método muestra la ruta de A, no B! Por lo tanto, esta respuesta no siempre ofrece lo que pide el OP.
Abhishek Anand
4
Cx Cv le mostrará no solo la ruta actual, sino también el nombre del archivo actual
kuzzooroo
@kuzzooroo, eso es adecuado para usuarios que no utilizan el modo ido (el nombre se muestra en Cx Cf con el uso del modo ido).
Julien Palard
16

La implementación directa de lo que desea es:

(defun copy-full-path-to-kill-ring ()
  "copy buffer's full path to kill ring"
  (interactive)
  (when buffer-file-name
    (kill-new (file-truename buffer-file-name))))

Dicho esto, me parece increíblemente útil poder obtener la ruta completa de lo que hay en el minibúfer, y esto es lo que uso:

(define-key minibuffer-local-completion-map "\C-r" 'resolve-sym-link)
(defun resolve-sym-link ()
  "Try to resolve symbolic links into true paths."
  (interactive)
  (beginning-of-line)
  (let* ((file (buffer-substring (point)
                                 (save-excursion (end-of-line) (point))))
         (file-dir (file-name-directory file))
         (file-true-dir (file-truename file-dir))
         (file-name (file-name-nondirectory file)))
    (delete-region (point) (save-excursion (end-of-line) (point)))
    (insert (concat file-true-dir file-name))))

Y luego, si lo quiero en el portapapeles, simplemente mato la línea ( C-a C-k). Pero podríamos copiar fácilmente el nombre verdadero al portapapeles en el comando anterior, simplemente cambie la última línea para que sea:

(insert (kill-new (concat file-true-dir file-name)))))

La parte nueva es la llamada a la 'kill-newque pone la cadena en el anillo de muerte.

Trey Jackson
fuente
¿Puede explicar cómo utilizar esta configuración? ¿Y qué significa "\ Cr"?
modelista
No importa. Me lo imaginé. Creo que es útil cuando estoy en modo ido y apuntando a un archivo, luego presiono Cr para obtener la ruta completa de ese archivo. De hecho útil. Sin embargo, todavía no sé por qué usar \ C en lugar de C.
modelista
11

No se necesitan funciones adicionales, solo

M-! pwd
gracias
fuente
Si bien esto puede funcionar, no funcionará en sistemas Windows y no tiene en cuenta el hecho de que el directorio de trabajo actual de emacs puede ser diferente del directorio del archivo del búfer actual. Puede ver esto por sí mismo visitando un archivo con C-x C-f, ejecutándolo M-! pwd, luego M-x cdseleccionando un directorio diferente y luego ejecutándolo M-! pwdnuevamente.
josaphatv
3

Tengo el siguiente código ya en uso durante mucho tiempo. Copia la ruta completa del archivo al kill ring cuando presiono el botón central del mouse en el nombre del búfer en la línea de modo. Copia solo el nombre del búfer en el kill-ring cuando presiono shift-mouse-2 en el nombre del búfer en la línea de modo.

(defun copy-buffer-file-name (event &optional bufName)
  "Copy buffer file name to kill ring.
If no file is associated with buffer just get buffer name.
"
  (interactive "eP")
  (save-selected-window
    (message "bufName: %S" bufName)
    (select-window (posn-window (event-start event)))
    (let ((name (or (unless bufName (buffer-file-name)) (buffer-name))))
      (message "Saved file name \"%s\" in killring." name)
      (kill-new name)
      name)))

(define-key mode-line-buffer-identification-keymap [mode-line mouse-2] 'copy-buffer-file-name)
(define-key mode-line-buffer-identification-keymap [mode-line S-mouse-2] '(lambda (e) (interactive "e") (copy-buffer-file-name e 't)))
Tobias
fuente
3

C-x C-d, también invocable mediante M-x list-directory, le mostrará el directorio de su archivo actual, y solo necesita presionar la tecla "Enter" para borrar el minibúfer. Detalles adicionales están disponibles aquí .

MLev
fuente
mi respuesta favorita, simple, rápida y fácil!
tictac
2

C-x C-b muestra una lista de búferes y la ruta del archivo para cada búfer cuando corresponda.

David
fuente
2

C-u C-x C-b enumera los búferes que actualmente visitan los archivos.

memeplex
fuente
1

¿Puedo copiar el nombre de la ruta en el portapapeles del sistema (SO), no en el kill ring, para poder usar la información con las otras aplicaciones?

Puede hacerlo si utiliza algo como xclip (Linux), pbcopy (Mac), putclip (Cygwin).

Yo personalmente uso scripts de envoltura cy ppara copiar y pegar respectivamente, la primera lectura de la entrada estándar, la última escritura en la salida estándar. De esa manera, esto funciona en todas mis plataformas de desarrollo:

(shell-command (format "echo '%s' | c" buffer-file-name))

Encuentro esto más confiable y configurable que usar el soporte del portapapeles de Emacs. Por ejemplo, mi ccomando copia la entrada a los 3 portapapeles en Linux (primario, secundario, portapapeles), por lo que puedo pegar con Ctrl-V o con un clic central.

Barry Kelly
fuente
Esto debería funcionar pero no para mí. (Ubuntu 14.04.1.) Es decir, date | xclipy xclip fileambos funcionan como se anuncia (almacenando la fecha o el contenido del archivo en primario) si se escribe en el shell. Pero si escribo cualquiera de estos comandos después de M-! en emacs (y presione regresar) no pasa nada; el cursor permanece en el minibúfer como si esperara más entrada; y si interrumpo para recuperar el control, no se ha almacenado nada en el primario.
Silvio Levy
De acuerdo, su idea funciona bien con xsel en lugar de xclip: (shell-command (format "echo '%s' | xsel -i" buffer-file-name))- y cuando se convierte en un comando interactivo (como se sugiere en la respuesta más votada por @JeromeRadix arriba), ¡esta es una GRAN GANANCIA! ¡Gracias!
Silvio Levy
0

La forma más sencilla y sería

(buffer-name)<(C-x)(C-e)> for the file name to appear in the echo area

(buffer-name)<(C-u)(C-x)(C-e)> would print the location <here>

Tomando prestado de Trey Jackson, se me ocurrió esto:

(defun buffer-kill-path ()
  "copy buffer's full path to kill ring"
  (interactive)
  (kill-new (buffer-file-name)))

Puede encontrar más información en el sitio.

DJJ
fuente