Де слід включити ліниву ініціалізацію?


13

Я хочу додати в режимі латексу певну прив'язку ключа:

(define-key latex-mode-map (kbd "<f6>") 'my-latex-defun)

У той же час я хочу його встановити лише при завантаженні конкретного режиму. Тому я хотів би знати, чи є перевага (найкраща практика) між використанням відповідного гака ( latex-mode-hook) для досягнення цього чи використанням пункту (with-eval-after-load "tex-mode" ...для завершення визначення обов'язкового ключа. Я тестував і те, і вони працюють нормально, проте мені цікаво, який з них - це правильний спосіб зробити це.


2
with-eval-after-loadзавантажується один раз , тому зміна ключової карти відбувається туди. Гачки завантажуються щоразу, коли запускається режим , наприклад, при завантаженні нового файлу, пов’язаного з режимом, або якщо гак визначений. Ви б завантажували, наприклад, flyspell-modeабо hl-line-modeв гачок. В моєму init.elя використовую with-eval-after-loadприблизно 160 разів і add-hook110 разів. Ледачий ініт - це добрий ініт (ІМО).
rasmus

@rasmus звучить як відповідь, якщо у вас є час :) На мою думку, відмінність того, скільки разів виконується код, є головним. (Це теж єдиний, про який я можу придумати…)
Шон Алред

Чому неправильно міняти ключові прив’язки в гаках режимів, див. Emacs.stackexchange.com/questions/990/…
tarsius

Відповіді:


18

Ледачий ініт - хороший ініт.

(ІМО)

Коли використовувати with-eval-after-load

with-eval-after-loadзавантажуються один раз , коли певна функція або файл буде першою завантажена, тому розкладка зміна явно йде в один з них. Не в останню чергу тому, що мапа клавіш може бути невідома в init-час [спробуйте щось на кшталт (define-key message-mode-map (kbd "C-c f") 'Footnote-add-footnote)in emacs -q]. Гачок не є приємним рішенням, оскільки він прив'язує функцію до клавіші щоразу, коли гак запускається. Як Tarsius замітки, ви можете дізнатися більше про те, чому НЕ на local-set-keyгачки.

Нарешті, зауважте, що with-eval-after-loadGNU Emacs 24.4 - це дворядкова обгортка навколо, eval-after-loadде bodyне потрібно цитувати.

Коли використовувати гачки

Гачки - це список функцій, що завантажуються щоразу, коли виконується критерій, наприклад, запускається певний режим. Загальне використання гаків - це завантаження другорядних режимів, таких як flyspell-modeабо hl-line-mode. Напр (add-hook 'org-agenda-mode-hook 'hl-line-mode). Як зазначає Ремі , add-hooksрозумний і зробить правильно, навіть якщо змінна гачок ще не завантажена. Тим не менш, у мене є багато таких статей, які можуть бути незначними для збільшення швидкості, але це дає відчуття організації та структури залежності:

(with-eval-after-load 'org-agenda
  (add-hook 'org-agenda-mode-hook 'hl-line-mode))

Навіщо додавати на гачок після org-agenda? Як завжди, C-h v org-agenda-mode-hook C-jпостачає. Гак визначається, org-agenda.elяк показано на рисунку *help*.

Завантаження додаткових функцій with-eval-after-load

with-eval-after-loadтакож важливо для завантаження додаткових функцій. Ви, мабуть, хочете щось схоже (with-eval-after-load 'org (require 'org-inlinetask))на завантаження org inlinetasks. Щоб зрозуміти, чому (find-library "org-inlinetask"). Оскільки org-inlinetasks.elбезпосередньо (require 'org), все приємне, autoloadщо ваші дружні сервіси Emacs поставилися до уваги, буде "проігноровано", і все org.el(c)буде завантажено.

Але що робити, якщо для вашого (особистого) defunпотрібно кілька місць? Якщо ви справді вибагливі, можете помістити defuns в інший файл у свій файл load-pathі додати autoloadфайли cookie, або ви можете сказати Emacs, де знайти функцію за допомогою autoloadфункції. Тоді щось подібне спрацювало б:

(autoload 'org-cdlatex-mode "org" "cdlatex mode from org.")
(with-eval-after-load "latex"
  (add-hook 'TeX-mode-hook 'org-cdlatex-mode))

Або ви могли так само, require orgяк це в свою чергу потягнеcdlatex

І, чесно кажучи, більшість часу особисті розбої не матимуть великого значення. 1150 рядків особистих порушень (84 винищування) init.elдодає 0,02 секунди над ванільним Emacs.

Вимірювання часу ініціалізації

Простий спосіб наблизити час до спонукання

time emacs --eval "(kill-emacs)"

(орієнтир проти emacs -q.

Але для отримання більш детального наближення до того, де знаходяться вузькі місця ініціалізації, перегляньте Джо Шафер esup.

Нарешті, час завантаження не зникає магічно. Ви лише підштовхуєте його вперед (до розширення, що використовуєте всі функції в кожному сеансі).


1
Вам не потрібно ставити додаток-гачок у-eval-after-load, тому що add-гак прив’яже змінну, якщо її ще немає.
Ремі

Ти правий! Чи все-таки можуть бути досягнуті швидкості від цього? [Я спробую оновити відповідь пізніше, щоб відобразити це]
rasmus

А як із засудами, які пізніше я хотів би прив’язати до гачка чи прив’язки ключів. Чи слід визначити вимикання за межами with-eval-after-loadбез втрати лінивих переваг ініціалізації?
jrbalderrama

5

На додаток до ваших пропозицій eval-after-loadта використання гачка, дозвольте мені запропонувати use-package.el. Ви можете робити все, що вам потрібно

(use-package latex
  :ensure auctex
  :bind ("<f6>" . my-latex-defun))

LaTeX не завантажуватиметься лише після того, як ви його запитаєте.

Як бічна примітка: ретельне використання use-packageскоротило час мого запуску до менше секунди. (Це займало близько чотирьох секунд.)


Дякую за пропозицію Я також розглядав можливість використання use-package, але мені дуже хочеться зрозуміти, як це зробити без додаткових пакетів.
jrbalderrama

1
Примітка @jrbalderrama, яка use-packageбуде поставлена ​​разом з Emacs 25.
Шон Аллред
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.