Tại sao tôi phải thêm từng gói vào đường dẫn tải? (hoặc Sự cố với gói request 'trong tệp init của tôi)


17

Mỗi lần tôi cài đặt một gói từ Menu Gói, nếu tôi thử gói requiređó trong tệp init của mình, tôi sẽ gặp lỗi trừ khi tôi thêm thủ công vào đường dẫn tải:

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

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

Điều đó thật tẻ nhạt. Và thường thì đường dẫn gói chứa số phiên bản. Nếu một gói đã được cập nhật, tôi phải chỉnh sửa thủ công đường dẫn tải.

Có cách nào để tự động hóa điều này?

Câu trả lời:


23

TL; DR:

Thêm dòng sau vào đầu tệp init của bạn ( .emacs.d/init.elhoặc .emacs):

(package-initialize)

Lời giải thích

Tạo thêm các tệp mà Emacs có thể sử dụng vì user-init-fileđây chắc chắn không phải là phương pháp phù hợp. Bởi vì hướng dẫn không nói cái nào được ưu tiên trong trường hợp có xung đột, ít nhất không phải ở phần bạn đã trích dẫn, tất cả điều này là để thêm sự nhầm lẫn - bây giờ chúng tôi không biết đó thực sự là gì user-init-file(giá trị mà bạn có thể muốn để kiểm tra để tìm hiểu).

Vì vậy, hãy bắt đầu bằng cách xóa tất cả các ứng cử viên ngoại trừ ~/.emacs.d/init.elthường được ưa thích (bởi người dùng) bởi vì nó không góp phần vào mớ hỗn độn đó $HOMEvà nó cho phép giữ tất cả các tệp cấu hình Emacs, kể cả tệp quan trọng nhất, dưới sự kiểm soát phiên bản chỉ sử dụng kho lưu trữ Emacs.

Theo mặc định, các cuộc gọi Emacs package-initialize sau khi tệp init của người dùng đã được tải. Tất cả đều như vậy , vì ngày nay hầu hết người dùng đều cài đặt các gói của họ bằng cách sử dụng package.el- vì vậy họ không cần phải làm bất cứ điều gì để các gói này được cung cấp.

Mặt khác, không phải ai cũng làm như vậy, nên không thể gọi package-initialize. Ngăn chặn chức năng đó được gọi được thực hiện bằng cách thêm (setq package-enable-at-startup nil)vào tệp init của người dùng (bạn có thể đặt nó ở đâu khác?).

package-initializekhông thể được gọi trước khi người dùng có thay đổi để bảo Emacs không làm điều đó và vì vậy nó phải được thực hiện sau khi tải tệp init. Miễn là người dùng chỉ cài đặt các gói và sau đó sử dụng chúng theo nguyên trạng hoặc tùy chỉnh chúng bằng giao diện Tùy chỉnh hoạt động tốt. Nhưng nếu bạn muốn tùy chỉnh các gói của mình bằng elisp thì bạn phải chắc chắn rằng chúng thực sự nằm trên load-pathtrước khi sử dụng các chức năng mà chúng xác định.

Điều đó khá dễ thực hiện và được ghi lại đúng cách (nếu tôi đã tìm hiểu trước, tôi sẽ không phải viết hầu hết những điều trên: - /

Lý do tải gói tự động xảy ra sau khi tải tệp init là tùy chọn người dùng chỉ nhận giá trị tùy chỉnh của họ sau khi tải tệp init, bao gồm các tùy chọn người dùng ảnh hưởng đến hệ thống đóng gói. Trong một số trường hợp, bạn có thể muốn tải các gói rõ ràng trong tệp init của mình (thường là do một số mã khác trong tệp init của bạn phụ thuộc vào một gói). Trong trường hợp đó, tệp init của bạn sẽ gọi hàm package-initialize. Tùy thuộc vào bạn để đảm bảo rằng các tùy chọn người dùng có liên quan, chẳng hạn như package-load-list(xem bên dưới), được thiết lập trước package-initializecuộc gọi. Bạn cũng nên đặt package-enable-at-startupthànhnil, để tránh tải lại các gói sau khi xử lý tệp init. Ngoài ra, bạn có thể chọn hoàn toàn ức chế tải gói khi khởi động và gọi lệnh 'Mx khởi tạo gói' để tải các gói của bạn theo cách thủ công.

Vì thế:

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

Tất nhiên, vấn đề (hoặc một vấn đề khác) cũng có thể là lỗi đánh máy Symbol's function definition is void: use-packgenằm trong tệp init của bạn và không xảy ra cho đến khi bạn nhập nó vào emacs.se.


1
Cũng được bảo hiểm tại stackoverflow.com/questions/11127109/ Lời
phils 31/12/14

Sử dụng (require 'use-package)trước đây có ổn (package-initialize)không?

3

Tôi nghĩ rằng after-init-hookgiải pháp được đề cập trong câu trả lời tràn ngăn xếp này nên được đề cập:

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

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

Tôi nghĩ rằng đây là cách nó đáng lẽ phải được thực hiện, nhưng những câu trả lời khác cung cấp thông tin về những cách khác để làm điều đó.


0

Sau đây thêm tất cả các thư mục bên dưới ~/.emacs.d/site-lispđể tải đường dẫn, vì vậy bạn chỉ có thể requiregói và bạn đã hoàn tất:

(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))
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.