Делюсь опытом в описанных технологиях. Блог в первую очередь выполняет роль памяток для меня самого.

Управление пакетами в EMACS с помощью use-package

Комментариев нет

Что такое use-package и как с ним бороться.

Автор данного пакета преследовал цель удобного управления своими пакетами, поддержание чистоты конфигурационных файлов EMACS и по возможности оптимизацию запуска. Ему удалось их успешно решить, а я решил воспользоваться результатами чуждого труда и заодно поделиться информацией. Почитать на англиском про use-package можно здесь, а в статье я лишь оставлю заметку о том, что реально пригодилось.

~/.emacs

Мой файл .emacs содержит довольно мало строк: установщик некоторых базовых пакетов, загрузчик файлов конфигурации, немного комментариев. Выглядит это всё так:

            ;;; package --- Summary
;;; Commentary:
;;; Main EMACS settings file, load settings from parts.

;;; Code:

(require 'package)

;;; Источники для установки пакетов. Дело в том, что MELPA Stable
;;; содержит не очень свежие версии, поэтому иногда лучше ставить
;;; пакеты из основного репозитория.

(add-to-list 'package-archives '("melpa-stable" . "http://stable.melpa.org/packages/"))
(add-to-list 'package-archives '("melpa"        . "http://melpa.org/packages/"))
(setq package-enable-at-startup nil)
(package-initialize nil)

;;; Если пакет use-package не установлен, его нужно скачать и
;;; установить
(unless (package-installed-p 'use-package)
  (message "EMACS install use-package.el")
  (package-refresh-contents)
  (package-install 'use-package))

;;; Установили, загрузили, указали, что недостающие пакеты нужно
;;; автоматически загружать и устанавливать.
(require 'use-package)
(setq use-package-always-ensure t)

;;; Указываем откуда брать части настроек.
(defconst user-init-dir
  (cond ((boundp 'user-emacs-directory) user-emacs-directory)
        ((boundp 'user-init-directory) user-init-directory)
        (t "~/.emacs.d/")))

;;; Функция для загрузки настроек из указанного файла.
(defun load-user-file (file)
  (interactive "f")
  "Load a file in current user's configuration directory"
  (load-file (expand-file-name file user-init-dir)))

;;; Части конфигурации. Порядок не имеет принципиального значения,
;;; однако я рекомендую некоторые базовые вещи помещать в начало,
;;; чтобы не было необходимости вспоминать базовые команды EMACS
;;; если в результате улучшения сломается один из базовых конфигов.
(load-user-file "neotree.el")
(load-user-file "personal.el")
(load-user-file "themes.el")
(load-user-file "flycheck.el")
(load-user-file "company.el")
(load-user-file "ibuffer.el")
(load-user-file "python.el")
(load-user-file "web.el")
(load-user-file "javascript.el")
(load-user-file "markdown.el")
(load-user-file "json.el")
(load-user-file "yasnippet.el")
(load-user-file "helm.el")
(load-user-file "keyboard.el")
(load-user-file "fonts.el")
(load-user-file "powerline.el")
(load-user-file "elisp.el")

;;; А здесь EMACS хранит настройки, задаваемые через customize
(setq custom-file "~/.emacs.d/customize.el")
(load-user-file "customize.el")

;;; .emacs ends here
        

Половина дела сделана. Настройки размещены в разных файлах, каждый из которых не зависит от других. Вот теперь заживём!

neotree.el

            ;;; Package --- Summary
;;; Commentary:
;;; NeoTree - sidebar for file browsing

;;; Code:

;;; Как я и говорил, пакет будет скачан и установлен автоматически.
(use-package
  neotree
  :bind ([f8] . neotree-toggle)      ;;; Так делается привязка клавиш.
  :init (setq neo-window-width 35)   ;;; Настройки ДО загрузки пакета.
  :config (setq neo-smart-open nil)) ;;; Настройки ПОСЛЕ загрузки пакета.

;;; neotree.el ends here
        

Полагаю, данный пример наглядно показывает, как пользоваться use-package. Продолжим.

personal.el

            ;;; Package --- Summary
;;; Commentary:
;;; User settings for .emacs

;;; Code:

;;; Закрывать *scratch* при запуске.
(kill-buffer "*scratch*")

;;; Цветные скобочки
(use-package
  rainbow-delimiters
  :init (add-hook 'prog-mode-hook #'rainbow-delimiters-mode)
        (setq rainbow-delimiters-max-face-count 9))

;;; Scrolling
(setq scroll-step               1) ;; one line
(setq scroll-margin            10) ;; scroll buffer to 10 lines at going to last line
(setq scroll-conservatively 10000)
(setq directory-free-space-args "-Pm")

;; Подсветка результатов поиска и всё такое
(setq search-highlight        t)
(setq query-replace-highlight t)

(setq column-number-mode 1) ;; Номера строк слева
(setq use-dialog-box nil)   ;; Не нужны нам диалоги, будем всё руками делать
(auto-fill-mode -1)         ;; Не знаю, что за параметр, так и не разобрался
(setq-default tab-width          4) ;; Заменить TAB на 4 пробела
(setq-default standart-indent    4) ;; Стандартный отступ - 4 пробела
(setq backup-inhibited t)           ;; Backup'ы тоже делать не будем
(setq auto-save-default nil)        ;; Автосохранение не нужно
(setq scroll-preserve-screen-position 10) ;; Показывать не менее 10 строк на экране

(setq-default c-basic-offset 4 c-indent-level 4 indent-tabs-mode nil) ;; TAB'ы не нужны

(setq-default save-place t) ;; Помнить, где был курсор в прошлый раз

;;; Нажатие Insert больше не включает режим замены
(define-key global-map [(insert)] nil)

;;; Автоформатирование перед сохранением
(defun format-current-buffer()
  (indent-region (point-min)
                 (point-max)))
(defun untabify-current-buffer()
  (if (not indent-tabs-mode)
      (untabify (point-min)
                (point-max)))
  nil)
(add-to-list 'write-file-functions 'untabify-current-buffer)
(add-to-list 'write-file-functions 'delete-trailing-whitespace)

(cua-mode 1)          ;;; Ctrl+C, Ctrl+V! Прямо как в Windows!
(desktop-save-mode 1) ;;; Помнить, какие файлы были открыты в прошлый раз
(fset 'yes-or-no-p 'y-or-n-p) ;;; Вместо yes и no понимать y и n
(global-hl-line-mode 1) ;;; Подсветка текущей строки
(global-linum-mode 1)   ;;; Показывать номера строк всегда
(menu-bar-mode -1)      ;;; А меню - никогда
(scroll-bar-mode -1)    ;;; Скроллбар не нужен
(tool-bar-mode -1)      ;;; Тулбар не нужен

;;; Умные скобочки
(use-package
  smartparens
  :config (smartparens-global-mode 1))

;; Electric pair mode
(electric-pair-mode 1)

;; Иконки в статус-баре
(use-package
  mode-icons
  :config (mode-icons-mode 1))

;; Показывать отступы во всех режимах
(use-package
  indent-guide
  :config (indent-guide-global-mode 1))

;;; Дерево отмены
(use-package
  undo-tree
  :config (global-undo-tree-mode 1))

;;; personal.el ends here
        

python.el

Очень интересный конфиг получается для Python.

            ;;; Package --- Summary
;;; Commentary:
;;; Settings for Python

;;; Code:

(defun annotate-pdb()
  (interactive)
  (highlight-lines-matching-regexp "import ipdb")
  (highlight-lines-matching-regexp "import pdb")
  (highlight-lines-matching-regexp "set_trace()")
  (highlight-regexp "^TODO ")
  (highlight-phrase "FIXME"))

(use-package
  python
  :mode ("\\.py'" . python-mode)
  :init (progn
          (defalias 'python2-mode 'python-mode)
          (defalias 'python3-mode 'python-mod))
  :config (setq-default py-separator-char 47) ;; Use spaces instead tab
  (setq-default python-indent-offset 4) ;; 4 spaces instead 2 for python-mode
  )

(use-package
  company-anaconda
  :ensure t
  :init (add-to-list 'company-backends 'company-anaconda))

(use-package
  py-autopep8
  :init (progn (add-hook 'python-mode-hook 'py-autopep8-enable-on-save)))

(use-package
  anaconda-mode
  :commands anaconda-mode
  :diminish anaconda-mode
  :init (progn (add-hook 'python-mode-hook 'anaconda-mode)
               (add-hook 'python-mode-hook 'eldoc-mode)
               (add-hook 'python-mode-hook 'annotate-pdb)))

(use-package
  pyvenv
  :config (defalias 'workon 'pyvenv-workon))

(use-package
  py-isort
  :config (setq py-isort-options '("-sl"))
  :init (progn (add-hook 'python-mode-hook 'py-isort-before-save)))

(use-package
  company-anaconda
  :config (add-to-list 'company-backends 'company-anaconda))

;;; python.el ends here 
        

Не уверен, что нужно что-то тут объяснять, но на всякий случай свой company.el тоже выставляю напоказ.

company.el

Этот модуль отвечает за подсказки и автозавершение. Он новее, чем autocomplete, и активно развивается. Большая часть плагинов дополнения сейчас пишется именно под него.

            ;;; Package --- Summary
;;; Commentary:
;;; Settings for company

;;; Code:

(use-package
  company
  :diminish company-mode
  :config (setq company-backends (remove 'company-ropemacs company-backends) company-tooltip-limit
                20 company-tooltip-align-annotations t)
  (global-company-mode 1))

;;; company.el ends here
        

Комментариев нет :

Отправить комментарий