Dlaczego muszę dodawać każdy pakiet do ścieżki ładowania? (lub Problem z pakietem wymaga w moim pliku init)

17

Za każdym razem, gdy instaluję pakiet z Menu Pakietu, jeśli spróbuję requirego w swoim pliku init, pojawia się błąd, chyba że ręcznie dodam go do ścieżki ładowania:

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

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

To nużące. I zwykle ścieżka pakietu zawiera numery wersji. Jeśli pakiet został zaktualizowany, muszę ręcznie edytować ścieżkę ładowania.

Czy jest jakiś sposób na zautomatyzowanie tego?

Nacięcie
źródło

Odpowiedzi:

23

TL; DR:

Dodaj następujący wiersz na górze pliku init ( .emacs.d/init.ellub .emacs):

(package-initialize)

Wyjaśnienie

Tworzenie większej liczby plików, które Emacs mógłby wykorzystać jako user-init-filezdecydowanie nie jest właściwym podejściem. Ponieważ instrukcja nie mówi, która jest korzystna w przypadku istnieje konflikt, przynajmniej w części, którą cytowany, wszystko to robi to na dodatek w błąd - teraz nie wiemy, co faktycznie jest user-init-file(którego wartość może chcesz sprawdzić, aby się dowiedzieć).

Zacznij więc od usunięcia wszystkich kandydatów, z wyjątkiem tego, ~/.emacs.d/init.elco jest ogólnie preferowane (przez użytkowników), ponieważ nie przyczynia się to do bezbożnego bałaganu $HOMEi pozwala na przechowywanie wszystkich plików konfiguracyjnych Emacsa, w tym najważniejszego, pod kontrolą wersji przy użyciu repozytorium tylko dla Emacs.

Domyślnie wywołania Emacsa package-initialize po załadowaniu pliku init użytkownika. Robi to w ogóle , ponieważ obecnie większość użytkowników instaluje swoje pakiety przy użyciu package.el- dlatego nie powinni oni nic robić, aby te pakiety były dostępne.

Z drugiej strony nie każdy ma, więc powinno być możliwe, aby nie nazywać package-initialize. Zapobieganie wywoływaniu tej funkcji polega na dodaniu (setq package-enable-at-startup nil)do pliku inicjującego użytkownika (gdzie indziej można go umieścić?).

package-initializenie może zostać wywołany, zanim użytkownik nie będzie musiał powiedzieć Emacsowi, aby tego nie robił, więc należy to zrobić po załadowaniu pliku init. Tak długo, jak użytkownik instaluje tylko pakiety, a następnie używa ich bez zmian lub dostosowuje je za pomocą niestandardowego interfejsu, który działa dobrze. Ale jeśli chcesz dostosować swoje pakiety za pomocą elisp, musisz upewnić się, że są one rzeczywiście włączone load-pathprzed użyciem funkcji, które definiują.

Jest to dość łatwe do wykonania i odpowiednio udokumentowane (gdybym najpierw to sprawdził, nie musiałbym pisać większości z powyższych: - /

Powodem automatycznego ładowania pakietu po załadowaniu pliku init jest to, że opcje użytkownika otrzymują swoje dostosowane wartości dopiero po załadowaniu pliku init, w tym opcje użytkownika wpływające na system pakowania. W niektórych okolicznościach możesz chcieć załadować pakiety jawnie do pliku init (zwykle dlatego, że jakiś inny kod w pliku init zależy od pakietu). W takim przypadku plik init powinien wywołać funkcję package-initialize. Od Ciebie package-load-listzależy, czy przed package-initializepołączeniem zostaną skonfigurowane odpowiednie opcje użytkownika, takie jak (patrz poniżej) . Powinieneś także ustawić package-enable-at-startupnanil, aby uniknąć ponownego ładowania pakietów po przetworzeniu pliku init. Alternatywnie, możesz całkowicie zablokować ładowanie pakietu podczas uruchamiania i wywołać polecenie `Mx pakiet-inicjalizacja ', aby ręcznie załadować pakiety.

Więc:

;;; .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

Oczywiście problemem (lub dodatkowym problemem) może być również to, że literówka Symbol's function definition is void: use-packgeznajduje się w pliku init i nie zdarzyła się, dopóki nie wpiszesz go w emacs.se.

Tarsjusz
źródło
1
Omówiono
Czy można używać (require 'use-package)wcześniej (package-initialize)?
陳 力
3

Myślę, że należy after-init-hookwspomnieć o rozwiązaniu wymienionym w odpowiedzi na przepełnienie stosu :

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

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

Myślałem, że tak właśnie powinno być, ale inne odpowiedzi dostarczają informacji o innych sposobach.

Znacząca nazwa użytkownika
źródło
0

Poniższe dodaje wszystkie katalogi ~/.emacs.d/site-lispdo ścieżki ładowania, więc możesz tylko requirepakiet i gotowe:

(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))
Cegła suszona na słońcu
źródło