Проблемы с инициализацией пакета Emacs 24

Мне кажется, что новая система пакетов, встроенная в Emacs 24, имеет некоторые недостатки, когда дело доходит до правильной загрузки и инициализации установленных пакетов.

Недавно я обновился до Emacs 24.1.1, который был обновлен 6/10/2012, и я пытался использовать встроенную систему пакетов и установил несколько пакетов, используя это, но все они имеют сходную проблему для автозагрузки и инициализации.

Например, я использую пакет под названием smex, который предоставляет улучшения для использования аккорда M-x. Для этого требуется определить ключ для M-x, поэтому я добавил (global-set-key (kbd "M-x") 'smex) в мой файл init.el. Но после запуска emacs я нажимаю аккорд M-x, и я получаю сообщение "Определение функции символа void: smex"... Если я также поместил (require 'smex) в мой файл init.el, я получаю сообщение об ошибке "Ошибка файла: Не удается открыть файл нагрузки, smex"

Добавление местоположения smex в переменную пути загрузки заставляет его работать, как ожидалось, однако, похоже, что оно полностью преследует цель иметь систему пакетов в первую очередь...

Любые мысли? Есть ли лучший способ или мы живем с этим ограничением на данный момент?

Ответ 1

Пакеты, которые вы устанавливаете с помощью package.el, активируются по умолчанию после, загружается ваш .emacs. Чтобы иметь возможность использовать их до конца вашего .emacs, вам необходимо активировать их с помощью команд:

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

Ответ 2

Стоит отметить, почему Emacs откладывает инициализацию пакета:

См. C-h i g (emacs) Package Installation RET, и в частности:

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

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

В качестве альтернативы, поскольку after-init-hook запускается после завершения стандартной инициализации пакета, вы можете использовать это для оценки любого кода инициализации, который зависит от пакетов. Поэтому вместо вызова package-initialize непосредственно в init.el вы могли бы написать:

(add-hook 'after-init-hook 'my-after-init-hook)
(defun my-after-init-hook ()
  ;; do things after package initialization
  )

ввод кода, требующего инициализированной системы пакетов в пределах этой функции.

YMMV.

(nb Я не тестировал подход after-init, поскольку я действительно не использую package.el, но я подтвердил последовательность событий в стартовом коде, поэтому я считаю, что он будет работать, как описано.)

1M-x customize-group RET package RET