Почему я должен добавить каждый пакет в путь загрузки? (или проблема с пакетом require 'в моем файле инициализации)

17

Каждый раз, когда я устанавливаю пакет из Меню пакетов, если я пытаюсь установить requireего в своем файле инициализации, я получаю сообщение об ошибке, если я не добавляю его вручную в путь загрузки:

(add-to-list 'load-path "/home/nick/.emacs.d/elpa/use-package-20141220.1645")

(require 'use-package-autoloads)
(require 'use-package)

Это утомительно. И обычно путь к пакету содержит номера версий. Если пакет был обновлен, я должен вручную отредактировать путь загрузки.

Есть ли способ автоматизировать это?

Ник
источник

Ответы:

23

TL; DR:

Добавьте следующую строку в начало вашего файла инициализации ( .emacs.d/init.elили .emacs):

(package-initialize)

Объяснение

Создание большего количества файлов, которые Emacs может использовать как user-init-fileопределенно, не является правильным подходом. Поскольку в руководстве не сказано, что предпочтительнее в случае возникновения конфликта, по крайней мере, не в той части, которую вы цитировали, все, что нужно сделать, это добавить путаницу - теперь мы не знаем, что на самом деле является user-init-file(чье значение вы могли бы хотеть осмотреть, чтобы выяснить).

Итак, начните с удаления всех кандидатов, кроме тех, ~/.emacs.d/init.elкоторые обычно предпочитаются (пользователями), потому что это не способствует возникновению нечестивого беспорядка $HOMEи позволяет хранить все файлы конфигурации Emacs, включая самый важный, под контролем версий, используя репозиторий только для Emacs.

По умолчанию Emacs вызывает package-initialize после загрузки файла инициализации пользователя. Он делает это на всех , потому что в наше время большинство пользователей устанавливают свои пакеты с помощью package.el- поэтому они не должны делать ничего , чтобы эти пакеты должны быть доступны.

С другой стороны, это делают не все , поэтому можно не звонить package-initialize. Предотвращение вызова этой функции осуществляется путем добавления (setq package-enable-at-startup nil)в файл инициализации пользователя (где еще вы можете поместить его?).

package-initializeне может быть вызвано до того, как у пользователя было изменение, чтобы сказать Emacs не делать этого, и это должно быть сделано после загрузки файла инициализации. Пока пользователь только устанавливает пакеты, а затем использует их как есть или настраивает их с помощью пользовательского интерфейса, который работает просто отлично. Но если вы хотите настроить свои пакеты, используя elisp, то вам нужно убедиться, что они действительно включены, load-pathпрежде чем использовать функции, которые они определяют.

Это довольно легко сделать и правильно задокументировать (если бы я сначала посмотрел это, мне не пришлось бы писать большую часть вышеперечисленного: - /

Причина, по которой автоматическая загрузка пакета происходит после загрузки файла инициализации, заключается в том, что пользовательские параметры получают свои настраиваемые значения только после загрузки файла инициализации, включая пользовательские параметры, которые влияют на систему упаковки. В некоторых случаях вы можете явно загружать пакеты в файл инициализации (обычно потому, что какой-то другой код в файле инициализации зависит от пакета). В этом случае ваш файл инициализации должен вызывать функцию package-initialize. Вы должны убедиться, что соответствующие параметры пользователя, такие как package-load-list(см. Ниже), установлены до package-initializeвызова. Вы должны также установить package-enable-at-startupвnil, чтобы избежать повторной загрузки пакетов после обработки файла инициализации. Или же вы можете полностью запретить загрузку пакетов при запуске и вызвать команду `Mx package-initialize ', чтобы загрузить ваши пакеты вручную.

Так:

;;; .emacs.d/init.el -- the `user-init-file'

(package-initialize)
(setq package-enable-at-startup nil)

(require 'use-package)

(use-package some-package
  :init (setq some-package-variable "foobar")

    ...

;;; .emacs.d/init.el ends here

Конечно, проблема (или дополнительная проблема) также может заключаться в том, что опечатка Symbol's function definition is void: use-packgeнаходится в вашем файле инициализации, и ее не было, пока вы не ввели ее в emacs.se.

Tarsius
источник
1
Также рассматривается на stackoverflow.com/questions/11127109/…
phils
Это нормально использовать (require 'use-package)раньше (package-initialize)?
力 力
3

Я думаю, что after-init-hookрешение, упомянутое в этом ответе переполнения стека, должно быть упомянуто:

(defun my-packages-init ()
  (require 'some-great-package))

(add-hook 'after-init-hook 'my-packages-init)

Я думал, что это было так, как это должно было быть сделано, но другие ответы предоставляют информацию о других способах сделать это.

Значимое имя пользователя
источник
0

Следующее добавляет все каталоги ~/.emacs.d/site-lispв путь загрузки, так что вы можете просто requireпакет и все готово:

(let* ((my-lisp-dir "~/.emacs.d/site-lisp/")
       (default-directory my-lisp-dir)
       (orig-load-path load-path))
  (setq load-path (cons my-lisp-dir nil))
  (normal-top-level-add-subdirs-to-load-path)
  (nconc load-path orig-load-path))
саман
источник