Verwenden Sie package.el zum Installieren und Aktualisieren, aber verwenden Sie-package zum Laden und Konfigurieren

15

Nachdem use-packageich kürzlich davon erfahren hatte, entschied ich mich, meine Konfiguration darauf zu portieren, wollte aber nicht auf die Bequemlichkeit verzichten package.el, Pakete zu installieren und sie auf dem neuesten Stand zu halten. Ich fand es ein wenig schwierig, use-packageund zu kombinieren package.el.

Ich bin im Allgemeinen daran interessiert zu lernen, wie sich Menschen use-packagemit dem package.elSystem verbinden, aber für eine genauere Frage lesen Sie weiter.

Folgendes möchte ich:

  1. Um Pakete vom Paketmanager installieren zu lassen, kann ich einfach nach Paketen suchen und diese auf dem neuesten Stand halten list-packages.
  2. Um Pakete ausschließlich über zu konfigurieren und zu laden use-package, kann ich in meiner Init-Datei leicht sehen, was ich lade und wie es konfiguriert ist.
  3. Optional möchte ich auch Pakete über use-packagedas :ensureSchlüsselwort von installieren können .

Wenn ich richtig verstehe, möchte ich sehr wenig von dem, was package-initializetut, im Grunde nur so, wie es das einrichtet load-path. Derzeit habe ich dies in meiner Konfiguration:

;(package-initialize)
(setq package-enable-at-startup nil)
(let ((default-directory "~/.emacs.d/elpa"))
  (normal-top-level-add-subdirs-to-load-path))
(require 'use-package)

Die erste, kommentierte, Zeile ist so, dass Emacs 25 (package-initialize)meiner Init-Datei nicht hilfreich ein hinzufügt . Das Bit mit normal-top-level-add-subdirs-to-load-pathist eine Annäherung an das, was package-initializedas machen würde load-path, eine Annäherung, die gut genug zu sein scheint.

Dies scheint meine Wünsche 1 und 2, aber nicht 3 zu erfüllen. Wenn ich versuche, es zu verwenden :ensure, erhalte ich eine Fehlermeldung, die besagt, dass package.eles nicht initialisiert ist. Ein Anruf package-initializewürde das beheben, aber ich möchte das vermeiden, da a) ich nicht alle unzähligen Autoloads laden möchte (ich bevorzuge use-packagees, genau die Autoloads zu erstellen, die ich benötige) und b) ich in der Lage sein möchte, einfach zu sein Vermeiden Sie es, bestimmte installierte Pakete zu laden, wann immer ich möchte (was einfach zu bewerkstelligen ist use-package).

Hat jemand eine Empfehlung, wie das geht?

Omar
quelle

Antworten:

11

IIUC, was Sie tun möchten, ist:

(package-initialize t)

Beachten Sie das tArgument, das der Schlüssel zu Ihrem Glück ist, da es package.el initialisiert (oder zumindest initialisieren sollte), ohne alle installierten Pakete zu aktivieren.

Stefan
quelle
1
Dies beantwortet meine Frage, obwohl ich mich jetzt dazu neige, zu verwenden, package-initializewas meine Frage in Frage stellt.
Omar
15

Mit Ihrer aktuellen Konfiguration haben Sie package.el effektiv deaktiviert , da Sie den Paketmanager nicht initialisieren und Emacs daran hindern, ihn automatisch zu initialisieren. Im Gegenzug müssen Sie nur ELPA hinzufügen load-path, aber das ist nur ein kleiner Teil dessen, was package.el tut. Ich bin nicht sicher, warum Sie das tun, aber es ist kein Setup, das ich empfehlen würde.

Insbesondere erhalten Sie bei Ihrem Ansatz keine automatischen Paketladevorgänge. Dies bedeutet, dass zunächst keine Befehle von einem Paket verfügbar sind.

Mit anderen Worten, es M-xwerden nur eingebaute Befehle angeboten. Um Befehle aus Ihren Paketen hinzuzufügen :commands, müssen Sie allen Ihren use-packageDeklarationen explizite Definitionen hinzufügen. Dies bedeutet einen hohen Wartungsaufwand, insbesondere für große Pakete wie Magit. Bei package.el erhalten Sie Autoloads kostenlos .


Das Kombinieren use-packagemit package.el ist eigentlich sehr einfach - das gesamte Setup basiert auf dieser Kombination -, aber es ist viel besser, package.el tatsächlich seinem Job zu überlassen. Initialisieren Sie einfach package.el ganz am Anfang Ihrer Init-Datei:

(require 'package)
(setq package-enable-at-startup nil)   ; To prevent initialising twice
(add-to-list 'package-archives '("melpa" . "https://stable.melpa.org/packages/"))

(package-initialize)

Aus Bequemlichkeitsgründen möchten Sie möglicherweise später ein Bootstrap durchführen use-package, sofern es nicht bereits installiert ist:

(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))

Damit können Sie eine Emacs-Sitzung auf einem neuen System starten, und Ihr init.el wird automatisch installiert use-package.

Letztendlich müssen Sie laden use-package:

(eval-when-compile
  (require 'use-package))

Jetzt können Sie use-packagePakete installieren und konfigurieren:

(use-package magit                      ; The one and only Git frontend
  :ensure t
  :bind (("C-c v c" . magit-clone)
         ("C-c v v" . magit-status)
         ("C-c v g" . magit-blame)
         ("C-c v l" . magit-log-buffer-file)
         ("C-c v p" . magit-pull))
   :config (setq magit-save-repository-buffers 'dontask))

Wenn Emacs dieses Formular jetzt beim Start auswertet, use-packagewird geprüft, ob Magit bereits installiert ist, und es wird bei Bedarf automatisch installiert.

Mondhorn
quelle
3
"Ich bin mir nicht sicher, warum Sie das tun": Der einzige Grund, den ich sehen kann, sind die Startzeiten: Es package-initializedauert einige Zeit, den Pfad zu füllen, Autoloads zu definieren und den Rest der Dinge zu erledigen. Ich glaube, ich habe irgendwo gelesen, dass Jon Wiegley selbst (der Autor von use-package) es vorzieht, alle automatisch geladenen Befehle in use-packageStrophen zu deklarieren, anstatt sich darauf zu verlassen package.el.
ffevotte
Das letzte Mal, als ich nachgesehen habe, hat er package.el überhaupt nicht verwendet, und ich glaube auf keinen Fall, dass Sie viel gewinnen werden. load-pathIn beiden Fällen müssen Sie die füllen und Autoloads hinzufügen, entweder über use-packageoder über package.el. Ich bezweifle, dass es einen messbaren Unterschied gibt, besonders wenn Sie ein modernes System mit einer schnellen Festplatte haben.
Lunaryorn
3
Einverstanden. Ich habe das Timing selbst gemacht. Mit einer schnellen Festplatte sehen Sie praktisch keinen großen Unterschied. Bei einer langsamen Festplatte kann der Startvorgang merklich langsamer sein (etwa 0,2 s) package-initializeals bei einer benutzerdefinierten Liste in load-path. Ich schreibe dies der "Erforschung" des Dateisystems zu, das dies package.eltut. Ich habe jedoch nie einen signifikanten Unterschied in der Leistung zwischen dem Laden von autoloadDefinitionen aus Dateien und deren Verwendung in use-packageZeilengruppen gemessen .
ffevotte
Nun, ich würde nicht sagen, dass ich das System deaktiviert habe package.el, ich würde sagen, dass ich nur deaktiviert habe package-initialize! Der Grund ist, dass ich, obwohl ich gerne list-packagesnach neuen Paketen suche und speziell alle meine derzeit installierten Pakete aktualisiere, das gezielte Laden von bevorzuge use-package. Für mich ist es eine gute Sache, Autoloads nur für Befehle zu haben, die ich verwende!
Omar
1
@ OmarAntolín-Camarena Warum nicht? Autoloads sind im Wesentlichen die öffentliche Schnittstelle eines Pakets mit Benutzereingriff. Seit package.el der Standard für die Verteilung von Paketen ist, können wir uns auf deren Vorhandensein verlassen.
Lunaryorn