Estoy tratando de conseguir shell-command
y async-shell-command
para integrarse perfectamente con un par de programas en mi .bashrc
archivo, 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 ~/.bashrc
archivo con:
... eval "$ (enlace directo $ 0)" echo "foo"
Dentro ~/code/foo
tengo un .envrc
archivo con:
RUTA de exportación = $ PWD / bin: $ RUTA echo "bar"
Si ejecuto M-x shell
con default-directory
set 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-directory
está quieto ~/code/foo
y 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-command
o start-process
hacer 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.envrc
archivo no lo está..envrc
evalú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-command
simplemente se ejecutacall-process
en el shell y pasa argumentos. Intenté esto en un shell normal:~/.bashrc
es de origen, pero el enlace directo no se ejecuta. Cuandodirenv hook bash
se ejecuta,_direnv_hook
se emite una función y se antepone aPROMPT_COMMAND
.Sospecho que eso
PROMPT_COMMAND
simplemente no funcionará. Sin embargo, eso no es un problema, porque_direnv_hook
es 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 -ic
porque no hay ninguna solicitud. Puedes cambiar la línea:eval "$(direnv hook $0)"
a:
eval "$(direnv hook $0)" && _direnv_hook
para 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-command
no 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-directory
set, 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-path
yprocess-environment
emacs se comportará como lo haría su shell: ejecute programas desde las rutas correctas y con el entorno correcto.fuente