Mengapa saya harus menambahkan setiap paket ke load-path? (atau Masalah dengan membutuhkan paket di file init saya)

17

Setiap kali saya menginstal sebuah paket dari Menu Paket, jika saya mencobanya requiredalam file init saya, saya mendapatkan kesalahan kecuali saya menambahkannya secara manual ke path-load:

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

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

Itu membosankan. Dan biasanya jalur paket berisi versi-angka. Jika sebuah paket diperbarui, saya harus mengedit path-load secara manual.

Apakah ada cara untuk mengotomatisasi ini?

Nick
sumber

Jawaban:

23

TL; DR:

Tambahkan baris berikut ke bagian atas file init Anda ( .emacs.d/init.elatau .emacs):

(package-initialize)

Penjelasan

Membuat lebih banyak file yang mungkin digunakan Emacs sebagai pendekatan user-init-fileyang jelas bukan yang tepat. Karena manual tidak mengatakan mana yang lebih disukai jika ada konflik, setidaknya tidak pada bagian yang Anda kutip, semua ini dilakukan untuk menambah kebingungan - sekarang kita tidak tahu yang sebenarnya adalah user-init-file(yang nilainya mungkin Anda inginkan untuk memeriksa untuk mencari tahu).

Jadi mulailah dengan menghapus semua kandidat kecuali ~/.emacs.d/init.elyang umumnya disukai (oleh pengguna) karena itu tidak berkontribusi pada kekacauan yang tidak suci itu $HOMEdan memungkinkan menjaga semua file konfigurasi Emacs, termasuk yang paling penting, di bawah kontrol versi menggunakan repositori hanya untuk Emacs.

Secara default, panggilan Emacs package-initialize setelah file init pengguna dimuat. Ia melakukannya sama sekali , karena saat ini sebagian besar pengguna menginstal paket mereka menggunakan package.el- sehingga mereka tidak harus melakukan apa pun untuk paket ini harus dibuat tersedia.

Di sisi lain tidak semua orang melakukannya, jadi harus dimungkinkan untuk tidak menelepon package-initialize. Mencegah fungsi itu dipanggil dilakukan dengan menambahkan (setq package-enable-at-startup nil)ke file init pengguna (di mana lagi Anda bisa meletakkannya?).

package-initializetidak dapat dipanggil sebelum pengguna memiliki perubahan untuk memberi tahu Emacs untuk tidak melakukannya, dan itu harus dilakukan setelah memuat file init. Selama pengguna hanya menginstal paket dan kemudian menggunakannya sebagaimana adanya atau mengkustomisasi mereka menggunakan antarmuka Kustom yang berfungsi dengan baik. Tetapi jika Anda ingin melakukan kustomisasi paket Anda menggunakan elisp maka Anda harus memastikan mereka benar-benar di load-pathsebelum menggunakan fungsi yang mereka tetapkan.

Itu cukup mudah dilakukan dan didokumentasikan dengan baik (jika saya sudah mencari yang pertama, saya tidak perlu menulis sebagian besar di atas: - /

Alasan pemuatan paket otomatis terjadi setelah memuat file init adalah bahwa opsi pengguna hanya menerima nilai yang disesuaikan setelah memuat file init, termasuk opsi pengguna yang mempengaruhi sistem pengemasan. Dalam beberapa keadaan, Anda mungkin ingin memuat paket secara eksplisit dalam file init Anda (biasanya karena beberapa kode lain dalam file init Anda tergantung pada suatu paket). Dalam hal ini, file init Anda harus memanggil fungsi package-initialize. Terserah Anda untuk memastikan bahwa opsi pengguna yang relevan, seperti package-load-list(lihat di bawah), diatur sebelum package-initializepanggilan. Anda juga harus menetapkan package-enable-at-startupuntuknil, untuk menghindari memuat paket lagi setelah memproses file init. Atau, Anda dapat memilih untuk sepenuhnya menghentikan pemuatan paket saat startup, dan menjalankan perintah `Mx package-initialize 'untuk memuat paket Anda secara manual.

Begitu:

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

Tentu saja masalahnya (atau masalah tambahan) juga bisa karena kesalahan ketik Symbol's function definition is void: use-packgeada di file init Anda dan tidak terjadi sampai Anda mengetiknya di emacs.se.

tarsius
sumber
Apakah boleh digunakan (require 'use-package)sebelumnya (package-initialize)?
陳 力
3

Saya pikir after-init-hooksolusi yang disebutkan dalam stack stack overflow ini harus disebutkan:

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

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

Saya pikir ini adalah cara yang seharusnya dilakukan, tetapi jawaban lain memberikan informasi tentang cara lain untuk melakukannya.

Nama Pengguna yang Berarti
sumber
0

Berikut ini menambahkan semua dir di bawah ~/.emacs.d/site-lispuntuk memuat path, sehingga Anda bisa hanya requirepaket dan Anda selesai:

(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
sumber