exec-path e $ PATH

28

Eu vi exemplos on-line em que as pessoas adicionam caminhos ao caminho padrão no Emacs com:

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

Sou novo no Elisp e acho que entendo o que a declaração acima faz, mas tenho algumas perguntas:

  • Em que ordem o Emacs pesquisa pelos caminhos de execução? Por exemplo, considera o valor de $PATH(variável de ambiente) (e se sim, antes ou depois exec-path?)

  • Como posso acrescentar vários desses caminhos? Posso apenas continuar concatenando-os? por exemplo

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

    ou devo fazer:

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

Eu também encontrei este pacote interessante no GitHub: exec-path-from-shell . Por que é necessário um pacote para isso?

Motivação

Já descobriu que um comando funciona no seu shell, mas não no Emacs?

Isso acontece muito no OS X, onde uma instância do Emacs iniciada na GUI herda um conjunto padrão de variáveis ​​de ambiente.

Essa biblioteca funciona resolve esse problema, copiando importantes variáveis ​​de ambiente do shell do usuário: solicita ao shell que imprima as variáveis ​​de interesse e depois as copia para o ambiente Emacs.

Amelio Vazquez-Reina
fonte
3
Bem-vindo ao Emacs e Elisp! Eu ainda sou bastante atualizado com o tópico e não sei as respostas para suas perguntas, mas pensei em mencionar algo que tornou a vida muito mais fácil: as funções de descrição. eg (describe-function 'add-to-list)( C-h f) fornecerá o documento para a add-to-listfunção, além de links para a fonte. Há também (describe-variable 'exec-path)( C-h v). Isso não é um comentário RTFM - esses documentos não respondem a todas as perguntas que você listou, apenas algo útil.
Jtmoulia 01/10/14
Obrigado @jtmoulia! Definitivamente vou manter isso em mente para perguntas futuras.
Amelio Vazquez-Reina
Além de C-h v exec-path, use o manual (s) (Emacs e Elisp). Em um manual, i exec-pathvocê será direcionado a uma explicação útil. Pergunte ao Emacs primeiro - você não vai se arrepender.
Drew

Respostas:

23

1) PATHeexec-path

O Emacs define a exec-pathpartir do valor de PATHna inicialização, mas não o verá novamente mais tarde. Mas se você executar um comando, ele herdará PATH, não exec-path, para que os subprocessos possam encontrar comandos diferentes dos do Emacs.

Como diz Francesco, isso pode ser especialmente confuso para shell-command, como isso não executar um processo diretamente, mas chama um shell para executá-lo, o que vai usar PATH, não exec-path.

2) Adicionando vários caminhos para exec-path

Basta ligar add-to-listrepetidamente:

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

Observe que isso add-to-listcontribui para o início da lista, portanto, isso acabará "PATH2"sendo o exec-pathanterior "PATH1".

Você também pode usar mais acesso "de baixo nível" às listas:

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

Isso adicionará "PATH1"e "PATH2"ao seu exec-path, nessa ordem.

3) CAMINHO DO Mac OS

O problema no Mac OS X é que o Mac OS não define o ambiente da mesma forma quando você chama um programa da interface do usuário global ou quando é chamado de um shell. Isso significa que a execução do Emacs a partir de um shell resultará na definição de diferentes variáveis ​​de ambiente do que quando você o executa no localizador. Isso é especialmente irritante se você definir variáveis ​​de ambiente .bashrciguais ou semelhantes, pois isso não afetará o Emacs "global".

Aparentemente, o pacote inicia um shell e importa variáveis ​​de ambiente a partir daí, imitando o ambiente que você obtém de um shell em um Emacs iniciado globalmente.

Jorgen Schäfer
fonte
Obrigado Jorgen. Em relação ao terceiro trimestre: você sabe onde o padrão PATHé definido para os programas iniciados a partir da interface do usuário global (ambiente de área de trabalho)? Estou tendo o mesmo problema com PYTHONPATHem elpy:). Quando inicio o Emacs a partir da área de trabalho, o Emacs não está ciente das minhas PYTHONPATHdefinições no meu .zshenvarquivo (um arquivo init para zsh), o que é muito frustrante, pois elpynão sabe onde encontrar meus pacotes Python. Estou feliz para mover essas PYTHONPATHdefinições para um shell diferente initarquivo (embora idealmente gostaria Emacs para usar as definições do meu .zshenv)
Amelio Vazquez-Reina
Receio não saber muito sobre o Mac OS X. Um rápido google me levou a stackoverflow.com/questions/135688/…, o que parece indicar que o launchd.conf é o lugar certo. Se tudo que você precisa disso para se Emacs, você pode, naturalmente, apenas definir tanto exec-pathe PATHna sua .emacs. Você pode definir PATHusando (setenv "PATH" (format "%s:%s" "/new/path/element" (getenv "PATH"))).
Jorgen Schäfer
Obrigado. Eu sei que o seguinte Q diverge um pouco do OP, mas existe alguma maneira de especificar no Emacs o PYTHONPATHque elpydeve ser usado?
Amelio Vazquez-Reina
Você pode modificar process-environment, por exemplo, usando setenv. Você pode fazer isso elpy-mode-hook, mas é uma variável globsl e torná-lo local de buffer pode facilmente levar a um comportamento confuso.
Jorgen Schäfer
9

Quando o emacs inicia um novo processo externo usando funções primitivas como call-processor start-process, o executável é pesquisado exec-path(e não $PATH)

No entanto, uma função como shell-commandinicia o shell como um subprocesso e transmite o comando que você deseja executar. Para executar este comando, o shell tentará encontrar o executável em $PATH(e não em exec-path).

Portanto, o exec-pathque conta mais para processos externos é iniciado pelo próprio emacs, enquanto o $PATHque conta para comandos que você executa com a função de nível superior (usando, M-!por exemplo)


Se você deseja adicionar vários diretórios exec-path, deve usar add-to-listvárias vezes.

Você pode fazer isso manualmente

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

ou usando um loop

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

Com relação à sua terceira pergunta, se o emacs foi iniciado a partir do ambiente de área de trabalho, ele herdará o ambiente, o que pode ser menos completo que o de um shell completo.

Isso significa que às vezes pode ser necessário concluir o valor do Emacs para $PATHusar o que um shell comum vê. Esse é o objetivo da exec-path-from-shellbiblioteca que você mencionou.

ffevotte
fonte