Estoy tratando de conseguir shell-commandy async-shell-commandpara integrarse perfectamente con un par de programas en mi .bashrcarchivo, específicamente direnv en este ejemplo.
Descubrí que si lo personalizaba shell-command-switch, podía obtener procesos de shell para cargar mi perfil como si fuera un shell de inicio de sesión interactivo normal:
(setq shell-command-switch (purecopy "-ic"))
(setq explicit-bash-args '("-ic" "export EMACS =; stty echo; bash"))
También estoy usando exec-path-from-shell .
Digamos que tengo un ~/.bashrcarchivo con:
... eval "$ (enlace directo $ 0)" echo "foo"
Dentro ~/code/footengo un .envrcarchivo con:
RUTA de exportación = $ PWD / bin: $ RUTA echo "bar"
Si ejecuto M-x shellcon default-directoryset to ~/code/foo, un shell bash cargará correctamente mi perfil y ejecutará el enlace directo para agregarlo a mi ruta:
direnv: cargando .envrc bar direnv: export ~ RUTA ~ / code / foo $ echo $ PATH / Usuarios / nombre de usuario / código / foo / bin: / usr / local / bin: ... # resto de $ PATH
Sin embargo, si default-directoryestá quieto ~/code/fooy ejecuto M-! echo $PATH, carga correctamente mi .bashrc pero no ejecuta el enlace direnv del directorio actual:
foo / usr / local / bin: ... # resto de $ PATH sin ./bin
Obtengo el mismo resultado si corro M-! cd ~/code/foo && echo $PATH.
¿Hay alguna manera de aconsejar o conectar shell-commando start-processhacer que se comporte como si se enviara desde un búfer de shell interactivo?
fuente

(setq shell-command-switch "-ic")entonces debe evaluarse junto con cualquier otro comando en ~ / .bashrc.eval "$(direnv hook $0)". Esto se está ejecutando, pero el mecanismo que debería activarse cuando está en un directorio específico con un.envrcarchivo no lo está..envrcevalúa nada en el archivo? ¿O son solo las variables de entorno que no se exportan? ¿Podría darme un ejemplo completo para que pueda intentar reproducir esto?Respuestas:
Esto no parece ser un problema con Emacs sino con bash.
shell-commandsimplemente se ejecutacall-processen el shell y pasa argumentos. Intenté esto en un shell normal:~/.bashrces de origen, pero el enlace directo no se ejecuta. Cuandodirenv hook bashse ejecuta,_direnv_hookse emite una función y se antepone aPROMPT_COMMAND.Sospecho que eso
PROMPT_COMMANDsimplemente no funcionará. Sin embargo, eso no es un problema, porque_direnv_hookes realmente simple. Simplemente podemos anteponereval $(direnv export bash)el comando de shell y funcionará:Esto imprimirá la ruta aumentada al búfer de mensajes. Alternativamente, ejecute con
M-!:No es necesario que
(setq shell-command-switch "-ic")esto funcione.fuente
eval "$(direnv export bash)"in elisp, pero esto fue extremadamente útil y me puso en el camino correcto.Ejecutar
eval "$(direnv hook $0)"define una función que se conecta$PROMPT_COMMAND, a la que nunca se llama cuando se ejecuta bashbash -icporque no hay ninguna solicitud. Puedes cambiar la línea:eval "$(direnv hook $0)"a:
eval "$(direnv hook $0)" && _direnv_hookpara llamar explícitamente a la función de enlace.
Editar: Acabo de darme cuenta de que rekado dio una respuesta muy similar.
fuente
$PROMPT_COMMAND.Gracias a Rekado y Erik por señalar cómo funciona el gancho direnv usando
$PROMPT_COMMAND. Comoshell-commandno usa un indicador, esto no se estaba ejecutando.Si bien la respuesta de Erik funciona en mi ejemplo de llamar a un comando de shell
M-!condefault-directoryset, no funcionaría en el siguiente ejemplo:Después de buscar en Google, encontré una manera de crear un enlace preexec en bash para ejecutar algo antes de ejecutar un comando. Tomé esta idea y la modifiqué para satisfacer mi necesidad de dirección. Así es como se ve la parte relevante de mi ~ / .bashrc ahora:
fuente
hoy en día es probable que desee utilizar https://github.com/wbolster/emacs-direnv
Funciona de manera similar al gancho que se instala directamente en su shell. el entorno de emacs se actualiza a pedido (o automáticamente al cambiar los buffers) para que coincida con lo que indica direnv es el entorno correcto para el directorio actual.
modificando
exec-pathyprocess-environmentemacs se comportará como lo haría su shell: ejecute programas desde las rutas correctas y con el entorno correcto.fuente