Estou tentando obter shell-command
e async-shell-command
integrar perfeitamente com alguns programas no meu .bashrc
arquivo, especificamente o direnv neste exemplo.
Descobri que, se eu personalizasse shell-command-switch
, poderia obter processos de shell para carregar meu perfil como se fosse um shell de logon interativo regular:
(setq shell-command-switch (purecopy "-ic")) (setq explícito-bash-args '("-ic" "exporta EMACS =; eco stty; bash"))
Eu também estou usando exec-path-from-shell .
Digamos que eu tenho um ~/.bashrc
arquivo com:
... avaliação "$ (gancho direnv $ 0)" eco "foo"
Dentro ~/code/foo
, tenho um .envrc
arquivo com:
exportar PATH = $ PWD / bin: $ PATH eco "bar"
Se eu executar M-x shell
com default-directory
set ~/code/foo
, um shell bash carregará meu perfil corretamente e executará o gancho direnv para adicioná-lo ao meu caminho:
direnv: carregando .envrc Barra direnv: exportação ~ PATH ~ / code / foo $ echo $ PATH / Usuários / nome de usuário / código / foo / bin: / usr / local / bin: ... # rest of $ PATH
No entanto, se default-directory
ainda está ~/code/foo
e eu corro M-! echo $PATH
, ele carrega corretamente meu .bashrc, mas não executa o gancho direnv do diretório atual:
foo / usr / local / bin: ... # resto de $ PATH sem ./bin
Eu obtenho o mesmo resultado se eu executar M-! cd ~/code/foo && echo $PATH
.
Existe uma maneira de aconselhar, conectar shell-command
ou start-process
fazer com que ele se comporte como se estivesse sendo enviado de um buffer de shell interativo?
fonte
(setq shell-command-switch "-ic")
, deverá ser avaliado juntamente com todos os outros comandos em ~ / .bashrc.eval "$(direnv hook $0)"
. Isso está sendo executado, mas o mecanismo que deve ser acionado quando você está em um diretório específico com um.envrc
arquivo não está..envrc
arquivo é avaliado? Ou são apenas variáveis de ambiente que não são exportadas? Poderia, por favor, fornecer um exemplo completo para que eu possa tentar reproduzir isso?Respostas:
Isso não parece ser um problema com o Emacs, mas com o bash.
shell-command
apenas executacall-process
no shell e passa argumentos. Eu tentei isso em um shell regular:~/.bashrc
é originário, mas o gancho direnv não é executado. Quandodirenv hook bash
é executada, uma função_direnv_hook
é enviada e anexada aPROMPT_COMMAND
.Eu suspeito que
PROMPT_COMMAND
simplesmente não vai funcionar. Porém, isso não é um problema, porque_direnv_hook
é realmente simples. Podemos simplesmente acrescentareval $(direnv export bash)
o comando shell e ele funcionará:Isso imprimirá o caminho aumentado para o buffer de mensagens. Como alternativa, execute com
M-!
:Você não precisa fazer
(setq shell-command-switch "-ic")
isso funcionar.fonte
eval "$(direnv export bash)"
in elisp, mas isso foi extremamente útil e me colocou no caminho certo.A execução
eval "$(direnv hook $0)"
define uma função que se conecta$PROMPT_COMMAND
, que nunca é chamada quando o bash é executado,bash -ic
porque não há prompt. Você pode alterar a linha:eval "$(direnv hook $0)"
para:
eval "$(direnv hook $0)" && _direnv_hook
chamar explicitamente a função de gancho.
Edit: Acabei de perceber que o rekado deu uma resposta muito semelhante.
fonte
$PROMPT_COMMAND
.Agradecemos a Rekado e Erik por apontarem como o gancho direnv funciona usando
$PROMPT_COMMAND
. Comoshell-command
não usa um prompt, isso não estava sendo executado.Embora a resposta de Erik funcione no meu exemplo de chamada de um comando shell
M-!
comdefault-directory
set, ela não funcionaria no exemplo a seguir:Depois de pesquisar no Google, encontrei uma maneira de criar um gancho preexec no bash para executar algo antes de um comando ser executado. Eu peguei essa ideia e modifiquei para atender minha necessidade de direnv. Aqui está a aparência da parte relevante do meu ~ / .bashrc agora:
fonte
hoje em dia você provavelmente gostaria de usar https://github.com/wbolster/emacs-direnv
funciona de forma semelhante ao gancho que o direnv instala no seu shell. o ambiente emacs é atualizado mediante solicitação (ou automaticamente ao alternar buffers) para corresponder a quais estados direnv é o ambiente correto para o diretório atual.
modificando
exec-path
e oprocess-environment
emacs se comportará como o seu shell faria: execute programas dos caminhos certos e com o ambiente certo.fonte