exec-path i $ PATH

28

Widziałem przykłady online, w których ludzie dodają ścieżki do domyślnej ścieżki w Emacsie za pomocą:

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

Jestem nowy w Elisp i myślę, że rozumiem, co robi powyższe stwierdzenie, ale mam kilka pytań:

  • W jakiej kolejności Emacs przeszukuje ścieżki wykonania? Na przykład, czy w ogóle bierze pod uwagę wartość $PATH(zmiennej środowiskowej) (a jeśli tak, przed czy po exec-path?)

  • Jak mogę wstawić wiele takich ścieżek? Czy mogę je po prostu łączyć? na przykład

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

    czy powinienem zrobić:

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

Znalazłem też ten interesujący pakiet na GitHub: exec-path-from-shell . Dlaczego potrzebny jest pakiet do tego?

Motywacja

Czy kiedykolwiek odkryłeś, że polecenie działa w twojej powłoce, ale nie w Emacsie?

Zdarza się to często w OS X, gdzie instancja Emacsa uruchomiona z GUI dziedziczy domyślny zestaw zmiennych środowiskowych.

Ta biblioteka działa rozwiązuje ten problem, kopiując ważne zmienne środowiskowe z powłoki użytkownika: działa, prosząc powłokę o wydrukowanie interesujących zmiennych, a następnie kopiując je do środowiska Emacsa.

Amelio Vazquez-Reina
źródło
3
Witamy w Emacs i Elisp! Nadal jestem całkiem świeży na ten temat i nie znam odpowiedzi na twoje pytania, ale pomyślałem, że wspomnę o czymś, co znacznie ułatwiło życie: opisywanie funkcji. eg (describe-function 'add-to-list)( C-h f) poda ci dokument add-to-listfunkcji, a także linki do źródła. Jest też (describe-variable 'exec-path)( C-h v). To nie ma być komentarz RTFM - te dokumenty nie odpowiadają na wszystkie pytania, które wymieniłeś, tylko coś przydatnego.
jtmoulia
Dzięki @jtmoulia! Na pewno będę o tym pamiętać podczas przyszłych pytań.
Amelio Vazquez-Reina
Oprócz tego C-h v exec-pathskorzystaj z instrukcji obsługi (Emacs i Elisp). W podręczniku i exec-pathzawiera pomocne wyjaśnienie. Najpierw zapytaj Emacsa - nie będziesz żałował, że tak zrobiłeś.
Drew

Odpowiedzi:

23

1) PATHiexec-path

Emacs ustawia exec-pathna podstawie wartości PATHprzy uruchomieniu, ale nie będzie na to patrzeć później. Ale jeśli uruchomisz polecenie, nie odziedziczy PATHono exec-path, więc podprocesy mogą znaleźć inne polecenia niż Emacs.

Jak mówi Francesco, może to być szczególnie mylące shell-command, ponieważ nie uruchamia to bezpośrednio procesu, ale wywołuje powłokę, aby go uruchomić, a PATHnie exec-path.

2) Dodanie wielu ścieżek do exec-path

Wystarczy dzwonić add-to-listwielokrotnie:

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

Zauważ, że add-to-listdodaje się na początku listy, więc skończy się "PATH2"to na exec-pathwcześniejszym "PATH1".

Możesz także skorzystać z większego „niskiego poziomu” dostępu do list:

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

To doda "PATH1"i "PATH2"do twojego exec-path, w tej kolejności.

3) ŚCIEŻKA Mac OS

Problem w Mac OS X polega na tym, że Mac OS nie ustawia środowiska tak samo, gdy wywołujesz program z globalnego interfejsu użytkownika lub gdy wywołujesz go z powłoki. Oznacza to, że uruchomienie Emacsa z powłoki spowoduje ustawienie różnych zmiennych środowiskowych niż podczas uruchamiania z wyszukiwarki. Jest to szczególnie denerwujące, jeśli ustawisz zmienne środowiskowe w .bashrclub podobne, ponieważ nie wpłynie to na „globalny” Emacs.

Pakiet najwyraźniej uruchamia powłokę i stamtąd importuje zmienne środowiskowe, naśladując środowisko, które otrzymujesz z powłoki w uruchomionym globalnie Emacsie.

Jorgen Schäfer
źródło
Dzięki Jorgen. Odnośnie do Q3: Czy wiesz, gdzie PATHjest zdefiniowane ustawienie domyślne programów uruchamianych z globalnego interfejsu użytkownika (środowisko pulpitu)? Mam ten sam problem z PYTHONPATHw elpy:). Kiedy uruchamiam Emacsa z pulpitu, Emacs nie wie o moich PYTHONPATHdefinicjach w moim .zshenvpliku (pliku init dla zsh), co jest bardzo frustrujące, ponieważ elpynie wie, gdzie mogę znaleźć moje pakiety Pythona. Z przyjemnością przenoszę te PYTHONPATHdefinicje do innego initpliku powłoki (chociaż idealnie chciałbym, aby Emacs używał definicji z mojego .zshenv)
Amelio Vazquez-Reina
Obawiam się, że w ogóle niewiele wiem o Mac OS X. Szybkie google doprowadziło mnie do stackoverflow.com/questions/135688/..., co wydaje się wskazywać, że launchd.conf jest właściwym miejscem. Jeśli wszystko, czego potrzebujesz, to Emacs, możesz oczywiście ustawić zarówno w swoim, jak exec-pathiw PATHswoim .emacs. Możesz ustawić PATHza pomocą (setenv "PATH" (format "%s:%s" "/new/path/element" (getenv "PATH"))).
Jorgen Schäfer
Dzięki. Wiem, że następujące Q różni się nieco od OP, ale czy jest jakiś sposób na określenie w Emacsie, PYTHONPATHktóry elpypowinien użyć?
Amelio Vazquez-Reina
Możesz zmodyfikować process-environment, na przykład używając setenv. Możesz to zrobić elpy-mode-hookwewnątrz, ale jest to zmienna globsl, a ustawienie jej na bufor lokalny może łatwo prowadzić do mylących zachowań.
Jorgen Schäfer
9

Kiedy emacs uruchamia nowy proces zewnętrzny przy użyciu prymitywnych funkcji, takich jak call-processlub start-process, plik wykonywalny jest przeszukiwany exec-path(a nie $PATH)

Jednak funkcja taka jak shell-commanduruchamia powłokę jako podproces i przekazuje polecenie, które chcesz uruchomić. Aby wykonać to polecenie, powłoka spróbuje znaleźć plik wykonywalny w $PATH(a nie w exec-path).

Dlatego exec-pathto, co najbardziej liczy się dla procesów zewnętrznych, które są uruchamiane przez samego emacsa, podczas gdy $PATHto, co liczy się dla poleceń uruchamianych za pomocą funkcji wyższego poziomu (używając M-!na przykład)


Jeśli chcesz dodać wiele katalogów exec-path, powinieneś użyć ich add-to-listwiele razy.

Możesz to zrobić ręcznie

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

lub za pomocą pętli

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

Jeśli chodzi o twoje trzecie pytanie, jeśli emacs został uruchomiony ze środowiska graficznego, dziedziczy po nim środowisko, które może być mniej kompletne niż środowisko pełnej powłoki.

Oznacza to, że czasami konieczne może być uzupełnienie wartości Emacsa za $PATHużycie tego, co widzi zwykła powłoka. Taki jest cel wspomnianej exec-path-from-shellbiblioteki.

ffevotte
źródło