Это третья часть серии статей Настройка Emacs с нуля.
Вы можете прочитать первую часть здесь, а вторую - здесь.

В последних двух частях мы изменили некоторые значения Emacs по умолчанию. Мы также установили два пакета и настроили их поведение по умолчанию. В этой части мы организуем нашу конфигурацию и сделаем ее переносимой с помощью use-package.

После первых двух частей наш init.el выглядит так:

Какие проблемы вы видите в этой конфигурации? Есть одна большая и одна небольшая проблема (и должно быть много, которые я пропустил).

  1. Эта установка непереносима.
  2. Структура кода слишком плоская.

Эта установка не переносится

Мы не можем просто перенести наш init.el с одного компьютера на другой, а затем ожидать, что у нас будут наши установочные порты Emacs. Как вы думаете, что произойдет, если вы скопируете свой init.el на новый компьютер?

Что предполагает наш код?
Указывает ли наш код Emacs на установку spacemacs-theme и company? Нет!
Мы предполагаем, что пакеты - spacemacs-theme и company уже будут там на всех компьютерах.

Когда вы открываете Emacs на новом компьютере, у него будут только пакеты Emacs по умолчанию. Так что вызов load-theme в нашем init.el завершится ошибкой. Включение режима компании также не удастся, так как на этом этапе ничего не называется company-mode. Таким образом, весь ваш код конфигурации, связанный с spacemacs-theme и company, либо выйдет из строя, либо будет неэффективным.
Примером, когда он не сработает, но будет неэффективным, является установка spacemacs-theme-comment-bg на nil. Этот звонок не подведет. Он просто создаст переменную. Но это будет неэффективно, поскольку нет пакета, который использует эту переменную.

Итак, вывод: Невозможно перенести эту установку без ручной установки всех пакетов.

Структура кода слишком плоская

В настоящее время наш код конфигурации не группируется по пакетам. Вы всегда можете сгруппировать его вручную, сохранив вместе все конфигурации пакета. Но это может быть трудно поддерживать. По мере того, как вы продолжаете добавлять пакеты и настраивать мелкие вещи здесь и там, легко распространить конфигурацию пакета по всему init.el.

На данный момент это может даже не казаться проблемой. Но по мере развития нашей установки это будет большой проблемой для управления установкой.

Есть много разных решений для двух вышеупомянутых проблем. Естественным способом решения первой проблемы будет ведение списка используемых нами пакетов и проверка, установлены ли они. Если какой-то пакет не установлен, установите его. Что-то вроде этого:

(defvar my-packages '(spacemacs-theme company))
(dolist (p my-packages)
  (when (not (package-installed-p p))
    (package-install p)))

Примечание. В Elips любая функция, оканчивающаяся на -p, является предикатом.

Это решение работает отлично.
Но для этого есть очень элегантное решение (которое также решает и вторую проблему).
Оно называется use-package .

Use-package

use-package - это макрос Elisp, написанный Джоном Вигли. Он упрощает и группирует конфигурацию для пакетов. Установите use-package, нажав:
(Теперь вы должны знать, как установить пакет.)

M-x package-install <RET> use-package <RET>

Обычное объявление пакета использования выглядит так:

(use-package <package-name>
  :init
  <code to be executed before loading the package>
  :config
  <code to be executed after loading the package>
  :bind
  <key bindings for this package>)

Примечание: любое слово, которому предшествует :, в Elisp называется keyword. Вы можете рассматривать ключевые слова как похожие на строки, но с другим назначением и присутствием.

Давайте посмотрим, как будет выглядеть объявление пакета использования для company. Наша текущая конфигурация для company:

(global-company-mode t)
(define-key company-active-map (kbd "C-n") 'company-select-next)
(define-key company-active-map (kbd "C-p") 'company-select-previous)
(setq company-idle-delay 0.0)

С use-package это будет выглядеть так:

(use-package company
  :bind (:map company-active-map
         ("C-n" . company-select-next)
         ("C-p" . company-select-previous))
  :config
  (setq company-idle-delay 0.3)
  (global-company-mode t))

Здесь мы говорим-

  1. Это объявление пакета использования company.
  2. В company-active-map привяжите C-n к company-select-next и C-p к company-select-previous.
    Обратите внимание на минимальный синтаксис здесь по сравнению с вызовом define-key.
  3. После загрузки company установите для company-idle-delay значение 0.3 и включите везде режим компании.

Теперь вся конфигурация, относящаяся к компании, естественным образом сгруппирована в объявлении пакета использования. В следующий раз, когда мы захотим внести некоторые изменения в company, мы перейдем к этому объявлению и добавим наш код. Таким образом, наша установка всегда будет хорошо сгруппирована. Итак, use-package решил нашу вторую проблему.

А как насчет первой проблемы? Будет ли use-package загружать недостающие пакеты?

Да, это будет. Вам просто нужно добавить в декларацию :ensure t. Например, посмотрите на это:

(use-package magit
  :ensure t
  :bind ("C-x g" . magit-status))

Примечание. Magit - потрясающий клиент git для Emacs, который вы должны использовать.

:ensure t обеспечит загрузку magit, если его там нет. Также обратите внимание на синтаксис bind здесь. Когда вы хотите сделать глобальную привязку (в отличие от bind в company, который был локальным для company-mode-map), синтаксис еще более минимален. Вам просто нужно указать (key-binding . command) пар. :)

use-package решил обе наши проблемы! :)

Примечание: в use-package есть еще много полезных (и очень хорошо продуманных) ключевых слов. Рекомендую пройти через README.md.

Примечание: хотя use-package - удобный макрос, мы должны знать, что происходит под капотом, когда мы его используем. Поскольку это всего лишь макрос, вы можете расширить его самостоятельно и посмотреть, что происходит. О расширении макросов читайте здесь.

Итак, наша установка теперь полностью переносима?
Нет! Есть еще одна небольшая проблема. use-package отсутствует в Emacs по умолчанию, и вы не можете использовать use-package для установки самого себя. :П

Итак, чтобы сделать нашу установку полностью переносимой, нам нужно проверить, установлен ли use-package, а если нет, нам нужно его установить.

(when (not (package-installed-p 'use-package))
  (package-refresh-contents)
  (package-install 'use-package))

Теперь наш init.el будет выглядеть примерно так:

Вот несколько пакетов (вместе с их конфигурациями), которые, я думаю, должны быть в каждой установке Emacs:

Заключение

В этой серии из трех частей о настройке Emacs с нуля мы увидели,

  • Способ редактирования текста Emacs.
  • Использование справочной системы, чтобы узнать, что происходит.
  • Настройка параметров Emacs по умолчанию.
  • Установка пакетов.
  • Организация вашей установки.
  • Делаем вашу установку портативной.

Делая это, мы увидели, насколько настраиваемым является Emacs! :)

Я не рассмотрел даже процента возможностей Emacs. Орг-режим сам по себе - тема другой (огромной) серии постов. И есть много других пакетов, которые делают Emacs особенным и уникальным.

Но я думаю, что мы уже сделали достаточно, чтобы продолжить работу самостоятельно.
Главное - знать, как использовать справочную систему Emacs.
(Извините за повторяя это снова и снова, но вы поймете всю мощь и удобство помощи Emacs по мере ее использования.)

Вы можете найти мою установку Emacs здесь. Не стесняйтесь одалживать вещи. Если вы найдете более эффективные способы, отправьте запросы на включение. :)
(Настоятельно рекомендуется держать вашу конфигурацию Emacs под контролем версий.)

Я должен упомянуть и поблагодарить Нарендру Джоши и Веданг Манерикар, поскольку я всегда крал (и с нетерпением жду возможности украсть) вещи из их конфигураций Emacs.

Советы по «Развитию вашей установки Emacs»

Стратегия, которую я использую для улучшения моей настройки Emacs, называется UFFL.
(Честно говоря, только я называю ее UFFL.)

Использование - Поиск болевых точек - Исправление - Зацикливание

Как вы уже догадались, я полностью придумал это, чтобы сделать его аналогом REPL. Но он хорошо описывает стратегию. :)

Внеся изменения в свою конфигурацию, я использую ее в течение нескольких дней для повседневных задач. Я часто нахожу некоторые болевые точки (то есть вещи, которые можно улучшить / автоматизировать / достичь меньшим количеством нажатий клавиш) при его использовании. Затем я нахожу решения этих проблем.
Обычно я пытаюсь решить проблемы самостоятельно, подбирая правильные параметры конфигурации или написав какой-нибудь Elisp. Затем я проверяю, есть ли решения в Emacs Stack Exchange (или где-нибудь в Интернете). В большинстве случаев решения из Интернета лучше и элегантнее, чем мои собственные.
Но я все же рекомендую найти / написать собственное решение, прежде чем искать в Интернете, чтобы вы стали лучше в Elisp и Emacs способ мышления. :)

И так будет вечно ...

Радость в путешествии!