exec-path y $ PATH

28

He visto ejemplos en línea donde las personas agregan rutas a la ruta predeterminada en Emacs con:

(add-to-list 'exec-path "/usr/local/bin/")

Soy nuevo en Elisp y creo que entiendo lo que hace la declaración anterior, pero tengo algunas preguntas:

  • ¿ En qué orden Emacs busca a través de las rutas de ejecución? Por ejemplo, ¿considera el valor de $PATH(variable de entorno) en absoluto (y si es así, antes o después exec-path?)

  • ¿Cómo puedo anteponer múltiples rutas de este tipo? ¿Puedo seguir concatándolos? p.ej

    (add-to-list 'exec-path "PATH1", "PATH2")
    

    o debería hacer:

    (add-to-list 'exec-path "PATH1:PATH2:PATH3") 
    

También encontré este paquete interesante en GitHub: exec-path-from-shell . ¿Por qué hay una necesidad de un paquete para esto?

Motivación

¿Alguna vez encontró que un comando funciona en su shell, pero no en Emacs?

Esto sucede mucho en OS X, donde una instancia de Emacs iniciada desde la GUI hereda un conjunto predeterminado de variables de entorno.

Esta biblioteca funciona resuelve este problema copiando variables de entorno importantes del shell del usuario: funciona pidiéndole al shell que imprima las variables de interés y luego las copie en el entorno Emacs.

Amelio Vazquez-Reina
fuente
3
¡Bienvenidos a Emacs y Elisp! Todavía estoy bastante fresco con el tema y no sé las respuestas a sus preguntas, pero pensé en mencionar algo que ha hecho la vida mucho más fácil: las funciones de descripción. por ejemplo (describe-function 'add-to-list)( C-h f) le dará el documento para la add-to-listfunción, así como enlaces a la fuente. También hay (describe-variable 'exec-path)( C-h v). Esto no pretende ser un comentario RTFM: estos documentos no responden todas las preguntas que enumeró, solo algo útil.
jtmoulia
Gracias @jtmoulia! Definitivamente lo tendré en cuenta para futuras preguntas.
Amelio Vazquez-Reina
Además de C-h v exec-path, use los manuales (Emacs y Elisp). En un manual, lo i exec-pathdirige a una explicación útil. Pregúntale a Emacs primero , no te arrepentirás de haberlo hecho.
Dibujó el

Respuestas:

23

1) PATHyexec-path

Emacs establece exec-pathdesde el valor de PATHinicio, pero no volverá a verlo más tarde. Pero si ejecuta un comando, heredará PATH, no exec-path, por lo que los subprocesos pueden encontrar comandos diferentes que Emacs.

Como dice Francesco, esto puede ser especialmente confuso shell-command, ya que no ejecuta un proceso directamente, sino que llama a un shell para ejecutarlo, que usará PATH, no exec-path.

2) Agregar múltiples rutas a exec-path

Solo llame add-to-listrepetidamente:

(add-to-list 'exec-path "PATH1")
(add-to-list 'exec-path "PATH2")

Tenga en cuenta que se add-to-listagrega al comienzo de la lista, por lo que esto terminará "PATH2"en el exec-pathantes "PATH1".

También puede usar más acceso de "bajo nivel" a las listas:

(setq exec-path (append '("PATH1" "PATH2")
                        exec-path))

Esto agregará "PATH1"y "PATH2"a su exec-path, en ese orden.

3) RUTA de Mac OS

El problema en Mac OS X es que Mac OS no configura el entorno de la misma manera cuando llama a un programa desde la IU global o cuando lo llama desde un shell. Esto significa que ejecutar Emacs desde un shell dará como resultado que se establezcan diferentes variables de entorno que cuando se ejecuta desde el buscador. Esto es especialmente molesto si configura variables de entorno en .bashrco similares, ya que eso no afectará a los Emacs "globales".

Aparentemente, el paquete inicia un shell e importa variables de entorno desde allí, imitando el entorno que se obtiene de un shell en un Emacs iniciado globalmente.

Jorgen Schäfer
fuente
Gracias Jorgen Con respecto a Q3: ¿Sabes dónde PATHse define el valor predeterminado para los programas iniciados desde la IU global (entorno de escritorio)? Estoy teniendo el mismo problema con PYTHONPATHen elpy:). Cuando inicio Emacs desde el escritorio, Emacs no conoce mis PYTHONPATHdefiniciones en mi .zshenvarchivo (un archivo init para zsh), lo cual es muy frustrante, ya elpyque no sabe dónde encontrar mis paquetes de Python. Estoy feliz de mover estas PYTHONPATHdefiniciones a un initarchivo de shell diferente (aunque idealmente me gustaría que Emacs use las definiciones de mi .zshenv)
Amelio Vazquez-Reina
Me temo que no sé mucho sobre Mac OS X. Un rápido google me llevó a stackoverflow.com/questions/135688/…, lo que parece indicar que launchd.conf es el lugar correcto. Si todo lo que necesita para esto es Emacs, por supuesto, puede configurar ambos exec-pathy PATHen su .emacs. Puedes configurarlo PATHusando (setenv "PATH" (format "%s:%s" "/new/path/element" (getenv "PATH"))).
Jorgen Schäfer
Gracias. Sé que la siguiente Q difiere un poco del OP, pero ¿hay alguna forma de especificar en Emacs lo PYTHONPATHque elpydebería usar?
Amelio Vazquez-Reina
Puede modificar process-environment, por ejemplo, utilizando setenv. Puede hacerlo elpy-mode-hook, pero es una variable global y hacer que sea local en el búfer puede conducir fácilmente a un comportamiento confuso.
Jorgen Schäfer
9

Cuando emacs inicia un nuevo proceso externo utilizando funciones primitivas como call-processo start-process, se busca el ejecutable exec-path(y no $PATH)

Sin embargo, una función como shell-commandinicia el shell como un subproceso y le pasa el comando que desea ejecutar. Para ejecutar este comando, el shell intentará encontrar el ejecutable en $PATH(y no en exec-path).

Por exec-pathlo tanto, es lo que más cuenta para los procesos externos que se inician por emacs, mientras que $PATHes lo que cuenta para los comandos que ejecuta usted mismo con una función de nivel superior (usando, M-!por ejemplo)


Si desea agregar múltiples directorios exec-path, debe usarlos add-to-listvarias veces.

Puedes hacerlo manualmente

(add-to-list 'exec-path "dir1")
(add-to-list 'exec-path "dir2")

o usando un bucle

(dolist (dir '("dir1" "dir2"))
  (add-to-list 'exec-path dir))

Con respecto a su tercera pregunta, si emacs se lanzó desde el entorno de escritorio, hereda el entorno del mismo, que podría ser menos completo que el de un shell completo.

Esto significa que a veces puede ser necesario completar el valor de Emacs para $PATHusar lo que ve un shell normal. Este es el propósito de la exec-path-from-shellbiblioteca que mencionas.

ffevotte
fuente