exec-path и $ PATH

28

Я видел примеры онлайн, где люди добавляют пути к пути по умолчанию в Emacs с помощью:

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

Я новичок в Elisp и думаю, что понимаю, что делает приведенное выше утверждение, но у меня есть несколько вопросов:

  • В каком порядке Emacs ищет пути выполнения? Например, учитывает ли он значение $PATH(env. Variable) вообще (и если да, то до или после exec-path?)

  • Как я могу добавить несколько таких путей? Могу ли я просто продолжать их объединять? например

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

    или я должен сделать:

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

Я также нашел этот интересный пакет на GitHub: exec-path-from-shell . Почему для этого нужна посылка?

мотивация

Считаете ли вы, что команда работает в вашей оболочке, но не в Emacs?

Это часто случается в OS X, где экземпляр Emacs, запущенный из GUI, наследует набор переменных среды по умолчанию.

Эта библиотека решает эту проблему путем копирования важных переменных среды из оболочки пользователя: она запрашивает у вашей оболочки печать переменных, представляющих интерес, а затем копирует их в среду Emacs.

Амелио Васкес-Рейна
источник
3
Добро пожаловать в Emacs и Elisp! Я все еще довольно свежа в этой теме и не знаю ответов на ваши вопросы, но я подумала, что упомяну кое-что, что сделало жизнь намного проще: функции описания. Например, (describe-function 'add-to-list)( C-h f) даст вам документ для add-to-listфункции, а также ссылки на источник. Там также (describe-variable 'exec-path)( C-h v). Это не комментарий RTFM - эти документы не отвечают на все вопросы, которые вы перечислили, просто что-то полезное.
Jtmoulia
Спасибо @jtmoulia! Я обязательно запомню это для будущих вопросов.
Амелио Васкес-Рейна
Кроме того C-h v exec-path, используйте руководство (я) (Emacs и Elisp). В руководстве, i exec-pathнаправляет вас к полезному объяснению. Сначала спросите Emacs - вы не пожалеете, что сделали.
Дрю

Ответы:

23

1) PATHиexec-path

Emacs устанавливает exec-pathзначение при PATHзапуске, но не будет смотреть на него позже. Но если вы запустите команду, она унаследует PATH, а не exec-pathтак, поэтому подпроцессы могут находить команды, отличные от Emacs.

Как говорит Франческо, это может быть особенно запутанным shell-command, поскольку он не запускает процесс напрямую, а вызывает оболочку для его запуска, которая будет использовать PATH, а не exec-path.

2) Добавление нескольких путей к exec-path

Просто позвоните add-to-listнесколько раз:

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

Обратите внимание, что это add-to-listдобавляет к началу списка, так что в конечном итоге это будет "PATH2"в exec-pathпредыдущем "PATH1".

Вы также можете использовать более низкоуровневый доступ к спискам:

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

Это добавит "PATH1"и "PATH2"к вам exec-path, в таком порядке.

3) Путь Mac OS '

Проблема в Mac OS X состоит в том, что Mac OS не устанавливает среду одинаково, когда вы вызываете программу из глобального пользовательского интерфейса или когда вы вызываете ее из оболочки. Это означает, что запуск Emacs из оболочки приведет к тому, что будут установлены переменные окружения, отличные от тех, которые вы запускаете из Finder. Это особенно раздражает, если вы устанавливаете переменные окружения .bashrcили подобные, так как это не повлияет на «глобальные» Emacs.

По всей видимости, пакет запускает оболочку и импортирует оттуда переменные среды, имитируя среду, которую вы получаете из оболочки в глобально запущенном Emacs.

Йорген Шефер
источник
Спасибо, Йорген. Относительно Q3: Вы случайно не знаете, где PATHзадано значение по умолчанию для программ, запускаемых из глобального пользовательского интерфейса (среды рабочего стола)? У меня та же проблема с PYTHONPATHв elpy:). Когда я запускаю Emacs с рабочего стола, Emacs не знает о моих PYTHONPATHопределениях в моем .zshenvфайле (файл инициализации для zsh), что очень расстраивает, так elpyкак не знает, где найти мои пакеты Python. Я счастлив перенести эти PYTHONPATHопределения в другой initфайл оболочки (хотя в идеале я хотел бы, чтобы Emacs использовал определения из моего .zshenv)
Амелио Васкес-Рейна
Боюсь, я совсем ничего не знаю о Mac OS X. Быстрый Google привел меня к stackoverflow.com/questions/135688/…, который, кажется, указывает, что launchd.conf - правильное место. Если все , что вам нужно это для является Emacs, вы можете, конечно , просто установить как exec-pathи PATHв вашем .emacs. Вы можете установить PATHс помощью (setenv "PATH" (format "%s:%s" "/new/path/element" (getenv "PATH"))).
Йорген Шефер
Спасибо. Я знаю, что следующий Q немного отличается от OP, но есть ли способ указать в Emacs, PYTHONPATHчто elpyследует использовать?
Амелио Васкес-Рейна
Вы можете изменить process-environment, например, используя setenv. Вы можете сделать это внутри elpy-mode-hook, но это переменная globsl, и ее локальное расположение в буфере может легко привести к путанице.
Йорген Шефер
9

Когда emacs запускает новый внешний процесс, используя примитивные функции, такие как call-processили start-process, исполняемый файл ищется exec-path(а не $PATH)

Однако такая функция, как shell-commandзапускает оболочку как подпроцесс и передает ей команду, которую вы хотите запустить. Чтобы выполнить эту команду, оболочка попытается найти исполняемый файл в $PATH(а не в exec-path).

Следовательно, именно это exec-pathимеет значение для внешних процессов, запускаемых самим emacs, тогда $PATHкак для команд, которые вы запускаете самостоятельно с помощью функции более высокого уровня ( M-!например,)


Если вы хотите добавить несколько каталогов exec-path, вы должны использовать add-to-listнесколько раз.

Вы можете сделать это вручную

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

или используя цикл

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

Что касается вашего третьего вопроса, если emacs был запущен из среды рабочего стола, он наследует от него среду, которая может быть менее полной, чем у полной оболочки.

Это означает, что иногда может потребоваться заполнить значение Emacs для $PATHиспользования того, что видит обычная оболочка. Это цель exec-path-from-shellбиблиотеки, которую вы упоминаете.

ffevotte
источник