Warum muss ich jedes Paket zum Ladepfad hinzufügen? (oder Problem mit require 'Paket in meiner Init-Datei)

17

Jedes Mal, wenn ich ein Paket aus dem Paketmenü installiere, requireerhalte ich eine Fehlermeldung , wenn ich es in meiner Init-Datei versuche, es sei denn, ich füge es manuell dem Ladepfad hinzu:

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

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

Das ist langweilig. Und normalerweise enthält der Paketpfad Versionsnummern. Wenn ein Paket aktualisiert wurde, muss ich den Ladepfad manuell bearbeiten.

Gibt es eine Möglichkeit, dies zu automatisieren?

Nick
quelle

Antworten:

23

TL; DR:

Fügen Sie die folgende Zeile oben in Ihre Init-Datei ein ( .emacs.d/init.eloder .emacs):

(package-initialize)

Die Erklärung

Es user-init-fileist definitiv nicht der richtige Ansatz, mehr von den Dateien zu erstellen, die Emacs verwenden könnte . Da das Handbuch nicht sagen , was in dem Fall bevorzugt wird , gibt es einen Konflikt, zumindest nicht in dem Teil , den Sie zitiert, all dies tut , ist fügen Verwirrung - jetzt wissen wir nicht , was eigentlich das ist user-init-file(deren Wert Sie möchten zu inspizieren, um herauszufinden).

Entfernen Sie daher zunächst alle Kandidaten, mit Ausnahme ~/.emacs.d/init.elderjenigen, die (von den Benutzern) im Allgemeinen bevorzugt werden, da dies nicht zu dem unheiligen Durcheinander beiträgt $HOMEund es Ihnen ermöglicht, alle Emacs-Konfigurationsdateien, einschließlich der wichtigsten, unter Versionskontrolle zu halten, indem Sie nur ein Repository für verwenden Emacs.

Standardmäßig ruft Emacs auf, package-initialize nachdem die Init-Datei des Benutzers geladen wurde. Er tut dies überhaupt , weil heutzutage die meisten Benutzer ihre Pakete mit installieren package.el- so sollten sie nichts zu tun haben , für diese Pakete zur Verfügung gestellt werden.

Auf der anderen Seite tut das nicht jeder , daher sollte es möglich sein, nicht anzurufen package-initialize. Um zu verhindern, dass diese Funktion aufgerufen wird, fügen Sie (setq package-enable-at-startup nil)sie der Init-Datei des Benutzers hinzu (wo können Sie sie sonst ablegen?).

package-initializekann nicht aufgerufen werden, bevor der Benutzer eine Änderung vorgenommen hat, um Emacs anzuweisen, dies nicht zu tun, und muss daher nach dem Laden der Init-Datei durchgeführt werden. Solange der Benutzer nur Pakete installiert und sie dann unverändert verwendet oder über die Benutzeroberfläche anpasst, funktioniert dies einwandfrei. Wenn Sie Ihre Pakete jedoch mithilfe von elisp anpassen möchten, müssen Sie sicherstellen, dass sie tatsächlich auf dem neuesten Stand sind, load-pathbevor Sie die von ihnen definierten Funktionen verwenden.

Das ist ziemlich einfach und richtig dokumentiert (wenn ich das zuerst nachgeschlagen hätte, hätte ich die meisten der oben genannten Dinge nicht schreiben müssen: - /

Der Grund für das automatische Laden von Paketen nach dem Laden der Init-Datei ist, dass Benutzeroptionen erst nach dem Laden der Init-Datei ihre benutzerdefinierten Werte erhalten, einschließlich Benutzeroptionen, die sich auf das Verpackungssystem auswirken. Unter bestimmten Umständen möchten Sie möglicherweise Pakete explizit in Ihre Init-Datei laden (normalerweise, weil ein anderer Code in Ihrer Init-Datei von einem Paket abhängt). In diesem Fall sollte Ihre Init-Datei die Funktion aufrufen package-initialize. Sie müssen sicherstellen, dass relevante Benutzeroptionen wie package-load-list(siehe unten) vor dem package-initializeAnruf eingerichtet werden. Sie sollten auch festlegen, package-enable-at-startupumnil, um zu vermeiden, dass die Pakete nach der Verarbeitung der Init-Datei erneut geladen werden. Alternativ können Sie das Laden von Paketen beim Start vollständig unterbinden und den Befehl `Mx package-initialize 'aufrufen, um Ihre Pakete manuell zu laden.

So:

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

Das Problem (oder ein zusätzliches Problem) könnte natürlich auch sein, dass sich der Tippfehler Symbol's function definition is void: use-packgein Ihrer Init-Datei befindet und erst dann aufgetreten ist, wenn Sie ihn in emacs.se eingegeben haben.

Tarsius
quelle
1
Ebenfalls beschrieben unter stackoverflow.com/questions/11127109/…
phils
Ist es in Ordnung, (require 'use-package)vorher zu verwenden (package-initialize)?
陳 力
3

Ich denke, die after-init-hookin dieser Stapelüberlaufantwort erwähnte Lösung sollte erwähnt werden:

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

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

Ich dachte, dies sei die Art und Weise, wie es gemacht werden sollte, aber die anderen Antworten geben Auskunft darüber, wie es anders gemacht werden kann.

Aussagekräftiger Benutzername
quelle
0

Der folgende Befehl fügt alle Verzeichnisse unter ~/.emacs.d/site-lispdem Ladepfad hinzu , sodass Sie nur requiredas Paket herunterladen und fertig sind:

(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))
Adobe
quelle