Конфигурация GNU Emacs

Emacs – текстовый редактор от сообщества GNU. Он расширяется при помощи языка Emacs Lisp и является одним из старейших текстовых редакторов, который используется многими и по сей день. Далее идёт моя конфигурация этого редактора.


Исходный код

Вклады

Список тех, у кого я тырил тот или иной код для конфига.

  • Copyright © 2018, 2019, 2020, 2021, 2022 Mikhail Kirillov <w96k.ru@gmail.com>
  • Copyright © 2021 Ivan Sokolov <ivan-p-sokolov@ya.ru>
  • Copyright © 2021 Protesilaos Stavrou <info@protesilaos.com>
  • Copyright © 2021 Bernt Hansen <bernt@norang.ca>

О конфигурации

Минимальная конфигурация Emacs. Пакеты ставлю через Guix, для разделения ответственности использую грамотное программирование при помощи org-mode.

Версия Emacs 28+.

  • В Guix пакет emacs-next.
  • В FreeBSD пакет emacs-devel.

Из программирования поддерживаются C, Java, Python, Common Lisp / Scheme, Haskell, Idris, Ocaml, Ruby, PHP, SML, SQL, Erlang, редактирование веб-шаблонов и различных форматов конфигураций. Какие-то языки в лучшей мере настроены, какие-то хуже, но есть почти все плюс-минус популярные.

Для систем контроля версий использую встроенный VC и в некоторых случаях Magit. Для входа в виртуальные среды используется Direnv.

Для ведения заметок использую методологию Zettelkasten при помощи org-roam. Для доступа к оффлайн википедии и другим ресурсам Kiwix клиент, который стучится на сервер, который стоит дома.

Для коммуникаций клиент для Telegram telega, для IRC erc и электронной почты gnus, для Mastodon mastodon.el.

Для системного администрирования имеют пакеты для работы с Debian, NixOS, Guix. Также есть поддержка Docker, Docker-compose: можно запускать/стопать контейнеры, а также залетать в них через TRAMP.

Для установки необходимо установить пакеты Emacs из ../../guix/user.scm и выполнить tangle файла при помощи M-x org-babel-tangle-file. В дальнейшем для развёртывания конфигурации можно использовать M-x config-tangle или M-x config-load.

Данная конфигурация доступна также в сети интернет по адресу, но так как сайт обновляется нечасто, то там может лежать старая версия: https://w96k.dev/emacs.html

Исходники конфигурации лежат на Sourcehut: https://git.sr.ht/~w96k/dotfiles/tree/master/item/emacs

Распространяется на условиях свободной лицензии GNU GPL v3, реиспользование одобряется пока распространяется под той же лицензией.

Пакеты

Данная конфигурация использует следующие пакеты:

Название Описание
Avy Прыжки по тексту
Anaconda Поддержка Python
Auctex Поддержка Tex и Latex
Browse Kill Ring Обзор буфера обмена
Haskell Mode Поддержка Haskell
Idris Mode Поддержка Idris
Magit Интерфейс к Git
Gitpatch Создание патчей
Goto Cgh Переход к последнему изменению в буфере
Debbugs Интерфейс к Debbugs
Deft Полнотекстовый поиск (использую для org-mode)
Direnv Изменение окружений при входе в директорию
Dumb Jump Прыжки по определениям при помощи grep и ему подобных
Docker Интерфейс к Docker
LSP-mode LSP клиент
Exec Path From Shell Синхронизация путей чтения из .bashrc в Emacs
Expand Region Семантическое расширение выделения на курсоре
Robe Прыжки по определениям в Ruby
Geiser REPL для Scheme
Git Gutters Отметки слева с изменением кода по гиту
Guix Интерфейс к GNU Guix
Org Roam Ведение связанных друг с другом заметок
Gnuplot Поддержка Gnuplot (графики)
Nix Mode Поддержка Nix
Pdf Tools Рендер PDF файлов в Emacs
PHP Mode Поддержка PHP
Kiwix Чтение скачанных архивов веб-страниц
SML Mode Поддержка Standard ML
Sly/Slime REPL Common Lisp
Simple HTTPD Простой сервер HTTP
Telega Интерфейс к Telegram
Treemacs Сайдбар для навигации по проекту
Undo Tree Визуализация дерева отмен
Yasnippet и Yasnippet Snippets Сниппеты для текста и языков программирования
xref  
Web Mode Поддержка веб-шаблонов

Следующий блок нужен для тех, кто хочет использовать встроенный пакетный менеджер. Я использую Guix для большей части взаимодействий со сторонним кодом.

(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)

(if (or (eq system-type 'berkeley-unix)
	(string-match-p (regexp-quote "Debian")
			(shell-command-to-string "lsb_release -d | awk -F\"\t\" '{print $2}'")))
    (when (not package-archive-contents)
      (progn
	(package-refresh-contents)
	(package-install 'avy)
	;; (package-install 'anzu)
	(package-install 'anaconda-mode)
	(package-install 'auctex)
	(package-install 'beginend)
	(package-install 'composer)
	(package-install 'cinspect)
	(package-install 'debian-el)
	(package-install 'dpkg-dev-el)
	(package-install 'edebug-inline-result)
	;;(package-install 'haskell-mode)
	;;(package-install 'idris-mode)
	(package-install 'magit)
	(package-install 'git-dwim)
	(package-install 'gitpatch)
	(package-install 'goto-chg)
	(package-install 'debbugs)
	;;(package-install 'deft)
	(package-install 'direnv)
	(package-install 'dumb-jump)
	(package-install 'docker)
	(package-install 'docker-cli)
	(package-install 'docker-tramp)
	;;(package-install 'eglot)
	(package-install 'mastodon)
	(package-install 'exec-path-from-shell)
	(package-install 'expand-region)
	(package-install 'flymake-php)
	(package-install 'flycheck)
	;;(package-install 'robe)
	(package-install 'geiser)
	(package-install 'geiser-guile)
	(package-install 'guix)
	(package-install 'git-gutter)
	(package-install 'gnuplot)
	;;(package-install 'swiper)
	;;(package-install 'sqlite3)
	(package-install 'org-roam)
	(package-install 'org-roam-ui)
	(package-install 'org-download)
	(package-install 'org-babel-eval-in-repl)
	(package-install 'ob-php)
	(package-install 'on-screen)
	;;(package-install 'nix-mode)
	(package-install 'pdf-tools)
	;;(package-install 'phpactor)
	;; (package-install 'company-quickhelp)
	(package-install 'ac-php)
	(package-install 'php-mode)
	(package-install 'php-quickhelp)
	(package-install 'phan)
	(package-install 'php-cs-fixer)
	;; (package-install 'company-php)
	(package-install 'php-eldoc)
	(package-install 'phps-mode)
	(package-install 'realgud)
	(package-install 'kiwix)
	;;(package-install 'sml-mode)
	(package-install 'slime)
	(package-install 'simple-httpd)
	(package-install 'sudo-edit)
	(package-install 'treemacs)
	(package-install 'undo-tree)
	(package-install 'yasnippet)
	(package-install 'yasnippet-snippets)
	(package-install 'vimrc-mode)
	(package-install 'flymake-phpcs)
	(package-install 'flymake-phpstan)
	(package-install 'no-littering)
	(package-install 'web-mode)
	(package-install 'which-key)
	(package-install 'reverse-im)
	(package-install 'restclient))))

Инициализация

Следующие блоки кода выводят в файл early-init.el

Компиляция

JIT компиляция elisp кода в машинный

(when (eq window-system 'pgtk)
  (pgtk-use-im-context t))

(when (fboundp 'native-compile-async)
    (setq comp-async-compilation t
      package-native-compile t

      native-comp-speed 2
      native-comp-async-jobs-number 1
      comp-num-cpus 2
      ;; JIT Compilation
      native-comp-deferred-compilation t
      ;; AOT Compilation
      package-native-compile t
      comp-async-report-warnings-errors nil))
  • Ручная компиляция
    ;; (native-compile-async "~/.emacs.d/elpa/" 'recursively)
    (native-compile-async "~/.guix-profile/share/emacs/site-lisp" 'recursively)
    
    ;; block until native compilation has finished
      (while (or comp-files-queue
    	     (> (comp-async-runnings) 0))
    

Отключаем ненужные загрузки

;; Disable guix autoloading and x resources loading
(setq site-run-file nil)

Редактируем GUI

Удаляем ненужные бары, меняем шрифт и модлайн. Использую дефолтный для Emacs шрифт DeJavu, так как он является одним из самых интернациональных шрифтов по количеству доступных символов после Unifont. Unifont я не стал использовать, потому что иксы замыливают этот пиксельный шрифт, что делает его использование крайне неприятным.

;; Do not resize the frame at this early stage.
(setq frame-inhibit-implied-resize t)
(setq use-dialog-box nil)

;;; Disable some gui
(scroll-bar-mode -1)
(tool-bar-mode -1)
(menu-bar-mode -1)
;;(tooltip-mode -1)

;; Change mode-line-modes to show only major mode
(defvar mode-line-major-mode
  (let ((recursive-edit-help-echo "Recursive edit, type C-M-c to get out"))
    (list (propertize "%[" 'help-echo recursive-edit-help-echo)
	  `(:propertize ("" mode-name)
			help-echo "Major mode\n\
    mouse-1: Display major mode menu\n\
    mouse-2: Show help for major mode\n\
    mouse-3: Toggle minor modes"
			mouse-face mode-line-highlight
			local-map ,mode-line-major-mode-keymap)
	  '("" mode-line-process)
	  (propertize "%n" 'help-echo "mouse-2: Remove narrowing from buffer"
		      'mouse-face 'mode-line-highlight
		      'local-map (make-mode-line-mouse-map
				  'mouse-2 #'mode-line-widen))
	  (propertize "%]" 'help-echo recursive-edit-help-echo)
	  " "))
  "Mode line construct for displaying major and minor modes.")

(put 'mode-line-major-mode 'risky-local-variable t)

;; Change mode-line-format
(setq-default mode-line-format
	      '("%e"
		mode-line-front-space
		mode-line-mule-info

		mode-line-client
		mode-line-modified
		mode-line-remote
		mode-line-frame-identification
		;; long-path
		mode-line-buffer-identification
		mode-line-misc-info
		"   "
		mode-line-major-mode
		" "
		vc-mode
		"  "

		mode-line-position
		mode-line-end-spaces
		))

;;; Changing emacs default setting through customize
(custom-set-variables
 '(fill-column 72)
 '(git-gutter:added-sign " ")
 '(git-gutter:deleted-sign " ")
 '(git-gutter:modified-sign " ")
 '(git-gutter:unchanged-sign " ")
 '(lsp-headerline-breadcrumb-enable nil)
 '(scroll-bar-mode 'nil)
 '(scroll-bar-adjust-thumb-portion nil)
 '(tool-bar-position 'bottom)
 '(tool-bar-style 'both-horiz))

(custom-set-faces
 '(default ((t (:height 145 :family "DejaVu Sans Mono" :embolden t))))
 '(region ((t (:background "gray90"))))
 '(mode-line ((t (:background "grey80" :foreground "grey10"))))
 '(mode-line-inactive ((t (:inherit mode-line :background "grey90" :foreground "grey20" :box (:line-width (-2 . -2) :color "grey85") :weight light))))
 '(mode-line-buffer-id ((t (:weight bold))))
 '(mode-line-emphasis ((t (:weight bold))))
 '(lsp-modeline-code-actions-face ((t :inherit mode-line :height 100)))
 '(tool-bar ((t (:background "grey80" :foreground "grey10"))))
 '(fill-column-indicator ((t (:foreground "grey95"))))
 '(hl-line ((t (:background "gray98"))))
 '(fringe ((t (:background "grey90"))))
 '(header-line ((t (:inherit mode-line :background "grey90"))))
 '(vertical-border ((t (:foreground "grey90"))))
 '(window-divider ((t (:foreground "gray90")))))

(set-fringe-style (cons 7 7))

(defun switch-gui ()
  "Disable/enable menu-bar and tool-bar."
  (interactive)
  (if menu-bar-mode
      (progn
	(menu-bar-mode -1)
	(tool-bar-mode -1)
	(scroll-bar-mode -1))
    (progn
      (menu-bar-mode 1)
      (tool-bar-mode 1)
      (scroll-bar-mode 1))))

(defun switch-scroll-bar ()
  "Disable/enable scroll-bar."
  (interactive)
  (if scroll-bar-mode
      (scroll-bar-mode -1)
    (scroll-bar-mode)))

(define-key global-map (kbd "<f5>") 'switch-gui)
(define-key global-map (kbd "<f8>") 'switch-scroll-bar)

(provide 'early-init)
    ;;; early-init.el ends here

Инициализируем остальной конфиг

Следующие блоки кода выводят в файл init.el.

;; -*- lexical-binding: t -*-

;; Show/Hide errors
;; (setq debug-on-error nil)
;; (setq debug-on-quit nil)

(defun package-loaded? (string)
  (if (or (cl-member string package-activated-list :test #'string=)
	  (ignore-errors (load (concat string "-autoloads"))))
      t
      (progn
	(message (concat "Package " string " is not loaded"))
	nil)))

;; Timer
(add-hook 'emacs-startup-hook
	  (lambda ()
	    (message
	     "Emacs ready in %s with %d garbage collections."
	     (format "%.2f seconds"
		     (float-time
		      (time-subtract after-init-time before-init-time)))
	     gcs-done)))

;; Dont ask when following symlinks
(setq vc-follow-symlinks t)

;; Load your custom settings
(setq custom-file "~/.emacs.d/custom-settings.el")
(load custom-file t)

Meta

Обо мне

;; Information about me
(setq user-full-name "Mikhail Kirillov"
      user-mail-address "w96k.ru@gmail.com")

Конфигурация

Базовые функции для манипулирования конфигом в дальнейшем, чтобы не приходилось танглить вручную.

(setq config-dotfiles-path "~/projects/dotfiles/emacs/.emacs.d/"
      config-path "~/.emacs.d/"
      config-name ".emacs-config.org")

(defun config-visit ()
  (interactive)
  (find-file (concat config-path config-name)))

(defun config-tangle ()
  (interactive)
  (org-babel-tangle-file (concat config-dotfiles-path config-name))
  ;; Configuration stored in another directory,
  ;; so I need to move files .emacs.d manually
  (rename-file (concat config-dotfiles-path "early-init.el") config-path t)
  (rename-file (concat config-dotfiles-path "init.el") config-path t))

(defun config-load ()
  (interactive)
  (org-babel-load-file (concat config-dotfiles-path config-name) t))

Внешний вид

Я использую по большей части стандартную тему имакса и стараюсь не менять стандартное поведение.

Назначение шрифтов

А также отступа между строк

;;; Set font
(setq-default line-spacing 0)

(set-language-environment "UTF-8")
(set-default-coding-systems 'utf-8-unix)

(setq mouse-wheel-progressive-speed nil)

Отображение номера строк и пробелов

Изначально они отключены, но можно вызвать по клавише F7.

(define-key global-map
  (kbd "<f7>") 'global-display-line-numbers-mode)

(define-key global-map
  (kbd "<f6>") 'whitespace-mode)

Скроллинг

Помечает на время часть старого буфера при скроллинге.

(when (package-loaded? "on-screen")
  (on-screen-global-mode t))

Объединение эхо зоны и модлайна

(when (package-loaded? "mini-modeline")
  (setq mini-modeline-r-format '("%e"
				 mode-line-front-space

				 mode-line-mule-info
				 mode-line-client
				 mode-line-modified
				 mode-line-remote

				 mode-line-frame-identification
				 ;;long-path
				 ;; mode-line-buffer-identification
				 mode-line-misc-info

				 mode-line-frame-identification
				 mode-line-major-mode

				 mode-line-frame-identification
				 vc-mode
				 mode-line-frame-identification

				 mode-line-position))

  (setq mini-modeline-truncate-p nil
	mini-modeline-display-gui-line nil)
  (mini-modeline-mode))

Отображать полный путь в header line

(defun with-face (str &rest face-plist)
  (propertize str 'face face-plist))

(defun sl/make-header ()
  ""
  (let* ((sl/full-header (abbreviate-file-name buffer-file-name))
	 (sl/header (file-name-directory sl/full-header))
	 (sl/drop-str "[...]"))
    (if (> (length sl/full-header)
	   (window-body-width))
	(if (> (length sl/header)
	       (window-body-width))
	    (progn
	      (concat (with-face sl/drop-str
				 :background "blue"
				 :weight 'bold
				 )
		      (with-face (substring sl/header
					    (+ (- (length sl/header)
						  (window-body-width))
					       (length sl/drop-str))
					    (length sl/header))
				 ;; :background "red"
				 :weight 'bold
				 )))
	  (concat (with-face sl/header
			     ;; :background "red"
			     :foreground "#8fb28f"
			     :weight 'bold
			     )))
      (concat (with-face sl/header
			 ;; :background "green"
			 ;; :foreground "black"
			 :weight 'bold
			 :foreground "#8fb28f"
			 )
	      (with-face (file-name-nondirectory buffer-file-name)
			 :weight 'bold
			 ;; :background "red"
			 )))))

(defun sl/display-header ()
  (setq header-line-format
	'("" ;; invocation-name
	  (:eval (if (buffer-file-name)
		     (sl/make-header)
		   "%b")))))

(add-hook 'buffer-list-update-hook
	  'sl/display-header)

Редактирование

Файловый менеджер

(setq dired-async-mode t)
;; Show files in KiB
(setq dired-listing-switches "-hlap"
      dired-kill-when-opening-new-dired-buffer t)

Линтер

Использую встроенный Flymake и Flycheck

  • Flymake
    ;;(add-hook 'prog-mode-hook 'flymake-mode)
    
    (define-prefix-command 'flymake-map)
    (global-set-key (kbd "C-q") 'flymake-map)
    (define-key flymake-map (kbd "n") 'flymake-goto-next-error)
    (define-key flymake-map (kbd "p") 'flymake-goto-prev-error)
    (define-key flymake-map (kbd "l") 'flymake-show-diagnostics-buffer)
    (define-key flymake-map (kbd "e") 'flymake-show-diagnostic)
    
  • Flycheck
    (when (package-loaded? "flycheck")
        (add-hook 'prog-mode-hook 'flycheck-mode))
    

Дерево проекта

Возможно в дальнейшем откажусь от этого пакета, так как по факту им пользуюсь нечасто. Он предоставляет дерево проектов, как в IDE.

(when (package-loaded? "treemacs")
  (progn
    (setq treemacs-width       50
	  treemacs-show-cursor t
	  treemacs-position    'right
	  treemacs-indentation 1
	  treemacs-tag-follow-mode t
	  treemacs-fringe-indicator-mode nil)

    (define-key global-map
      (kbd "C-x C-d") 'treemacs)))

Дерево imenu

(when (package-loaded? "imenu-list")
  (setq imenu-list-focus-after-activation nil
	imenu-list-auto-resize nil
	imenu-list-mode-line-format '()
	imenu-list-size 0.4)
  (global-set-key (kbd "C-x C-d") #'imenu-list-smart-toggle))

Better Isearch

(when (package-loaded? "isearch-mb")
  (progn
    (isearch-mb-mode t)
    (global-set-key (kbd "C-s") 'isearch-forward-regexp)
    (global-set-key (kbd "C-r") 'isearch-backward-regexp)))

Система контроля версий

Модуль VC + Magit.

Operation VC Magit
Project status project-vc-dir (C-x p v) magit-status (C-x g)
Pull vc-update (F, in my case) magit-pull (F p)
New branch vc-retrieve-tag (C-u B s) magit-branch (b c)
Commit vc-next-action (C-x v v) magit-commit (c c)
Rebase shell-command (M-!) + git rebase master magit-rebase (r p)
Push vc-push (P or C-u P) magit-push (P p)
Stash mu-vc-git-stash (z) magit-stash (z)
Log vc-print-root-log (L) magit-log (l l)

https://www.manueluberti.eu//emacs/2021/11/27/vc/

  (setq vc-command-messages t)

  ;;(load "git-dwim-autoloads")

  (global-set-key "\C-xvB" 'git-branch-next-action)

  ;; Fix for transient to behave like a normal buffer
;; (with-eval-after-load 'transient
;;   (setq
;;    transient--buffer-name "*transient*"
;;    ;; transient-detect-key-conflicts t
;;    ;; transient-highlight-mismatched-keys t
;;    ;; transient--debug t
;;    transient-enable-popup-navigation t
;;    transient-mode-line-format mode-line-format
;;    transient-display-buffer-action '(display-buffer-below-selected))

;;   (let ((map transient-base-map))
;;     (define-key map (kbd "C-g") 'transient-quit-all)
;;     (define-key map (kbd "C-q") 'transient-quit-one)
;;     (define-key map (kbd "DEL") 'transient-quit-one))

;;   (define-key transient-map (kbd "C-h") nil)

;;   (let ((map transient-popup-navigation-map))
;;     (define-key map (kbd "<tab>") 'transient-forward-button)
;;     (define-key map (kbd "<backtab>") 'transient-backward-button ))

;;   (transient-suffix-put 'transient-common-commands
;; 			"C-g" :command 'transient-quit-all)
;;   (transient-suffix-put 'transient-common-commands
;; 			"C-q" :command 'transient-quit-one)

;;   (defun al/transient-fix-window ()
;;     "Return `transient--window' to a 'normal' state."
;;     (set-window-dedicated-p transient--window nil)
;;     (set-window-parameter transient--window 'no-other-window nil)
;;     (with-selected-window transient--window
;;       (setq
;;        window-size-fixed nil
;;        cursor-in-non-selected-windows t
;;        cursor-type (default-value 'cursor-type)
;;        mode-line-buffer-identification
;;        (list ""
;; 	     (symbol-name (oref transient--prefix command))
;; 	     " " (default-value 'mode-line-buffer-identification)))))

;;   (define-derived-mode al/transient-mode special-mode "al/transient"
;;     (setq buffer-read-only nil)
;;     (al/transient-fix-window))

;;   (defun al/transient-push-keymap (map)
;;     (with-demoted-errors "al/transient-push-keymap: %S"
;;       (internal-push-keymap (symbol-value map) 'al/transient-mode-map)))

;;   (defun al/transient-pop-keymap (map)
;;     (with-demoted-errors "al/transient-pop-keymap: %S"
;;       (internal-pop-keymap (symbol-value map) 'al/transient-mode-map)))

;;   (defun al/transient-fix-show (&rest _)
;;     (transient--debug 'al/transient-fix-show)
;;     (al/transient-fix-window)
;;     (select-window transient--window))

;;   (defun al/transient-fix-init (&rest _)
;;     (transient--debug 'al/transient-fix-init)
;;     (with-current-buffer transient--buffer-name
;;       (al/transient-mode)))

;;   (defun al/transient-fix-pre/post-command (fun &rest args)
;;     (transient--debug 'al/transient-fix-pre/post-command)
;;     ;; Do anything only for transient commands.
;;     (when (or (get this-command 'transient--prefix)
;; 	      (string-match-p "\\`transient"
;; 			      (symbol-name this-command))
;; 	      (and transient--transient-map
;; 		   (string= (buffer-name) transient--buffer-name)
;; 		   (lookup-key transient--transient-map
;; 			       (this-single-command-raw-keys))))
;;       (apply fun args)))

;;   (defun al/transient-fix-delete-window (fun &rest args)
;;     (unless (eq transient--exitp 'suspend)
;;       (apply fun args)))

;;   (advice-add 'transient--minibuffer-setup :override #'ignore)
;;   (advice-add 'transient--minibuffer-exit :override #'ignore)
;;   (advice-add 'transient--push-keymap :override #'al/transient-push-keymap)
;;   (advice-add 'transient--pop-keymap :override #'al/transient-pop-keymap)
;;   (advice-add 'transient--pre-command :around #'al/transient-fix-pre/post-command)
;;   (advice-add 'transient--post-command :around #'al/transient-fix-pre/post-command)
;;   (advice-add 'transient--show :after #'al/transient-fix-show)
;;   (advice-add 'transient--init-transient :after #'al/transient-fix-init)
;;   (advice-add 'transient--delete-window :around #'al/transient-fix-delete-window))

  ;; Use magit only when built-in VC fails
  (when (package-loaded? "magit")
    (progn
      (setq magit-refresh-status-buffer nil)
      (global-set-key (kbd "C-x g") 'magit-status)))
  • Пометки о модифицированных строках

    Если строка добавлена, удалена или отредактирована относительно текущего git проекта, то строка помечается зеленым, красным или желтым цветом соответственно.

    ;;; Show added & removed git lines
    (when (package-loaded? "git-gutter")
      (progn
        (global-set-key (kbd "<f9>") 'git-gutter-mode)
    
        (setq git-gutter-window-width 1)
    
        (with-eval-after-load "git-gutter"
          '(set-face-background 'git-gutter:added "#99cc99")
          '(set-face-background 'git-gutter:deleted "#f2777a")
          '(set-face-background 'git-gutter:modified "#ffcc66")
          '(set-face-background 'git-gutter:unchanged "#f6f5f4"))
    
        (custom-set-variables
         '(git-gutter:modified-sign " ")
         '(git-gutter:unchanged-sign " ")
         '(git-gutter:added-sign " ")
         '(git-gutter:deleted-sign " "))))
    

Прыжки

(when (package-loaded? "avy")
  (progn
    (define-key global-map (kbd "M-s M-s") 'avy-goto-char)
    (define-key global-map (kbd "M-s s") 'avy-goto-char)
    (define-key global-map (kbd "M-s g") 'avy-goto-line)
    (define-key global-map (kbd "M-s l") 'avy-goto-char-in-line)
    (define-key global-map (kbd "M-s M-l") 'avy-goto-char-in-line)

    ;; Rewrite default bind to avy
    (define-key global-map (kbd "M-g g") 'avy-goto-line)
    (define-key global-map (kbd "M-g M-g") 'avy-goto-line)))

(when (package-loaded? "link-hint")
  (progn
    (define-key global-map (kbd "M-s j") 'link-hint-open-link)))

;; Прыжок на последнее изменение
(when (package-loaded? "goto-chg")
  (progn
    (setq glc-default-span 2)
    (define-key global-map (kbd "C-z") 'goto-last-change)
    (define-key global-map (kbd "M-z") 'goto-last-change-reverse)))

;; Dumb Jump
(when (package-loaded? "dumb-jump")
  (progn
    (define-key global-map (kbd "C-.") 'dumb-jump-go)))

Проекты

Использую встроенный project.el I use built-in project.el

Ограничение ширины строки

(when (package-loaded? "visual-fill-column")
  (progn
    ;;; Column width limit highlighter
    (add-hook 'prog-mode-hook 'display-fill-column-indicator-mode)

    ;;; Set column width to 79 according to pep8 for python
    (add-hook 'python-mode-hook
	      (lambda () (set-fill-column 79)))))

Подсвечивание парных скобок

;;; Show pair for a parenthesis
(show-paren-mode)

Ввод парных скобок и кавычек (electric)

;;; Input of pair delimiters
(electric-pair-mode)
(add-hook 'prog-mode-hook 'electric-pair-mode)
;; (add-hook 'prog-mode-hook 'rainbow-identifiers-mode)

Kill-ring

(when (package-loaded? "browse-kill-ring")  
  (define-key global-map (kbd "C-M-y") 'browse-kill-ring))

Tags

Для прыжков и поиска функций/классов и т.д.

(setq path-to-ctags "~/.guix-profile/bin/ctags")

(defun tags-create (dir-name)
  "Create tags file."
  (interactive "DDirectory: ")
  (shell-command
   (format "%s -f TAGS -e -R %s" path-to-ctags
	   (directory-file-name dir-name))))

(defun tags-create-python (dir-name)
  "Create tags with python interpreter"
  (interactive "DDirectory: ")
  (shell-command
   (format "%s -f TAGS -e -R --fields=+l --languages=python --python-kinds=-iv $(python -c \"import os, sys; print(' '.join('{}'.format(d) for d in sys.path if os.path.isdir(d)))\") %s" path-to-ctags
	   (directory-file-name dir-name))))  

Дополнение

Дебаггер

(when (package-loaded? "realgud")
  (load "~/.emacs.d/site-lisp/realgud-xdebug/realgud-xdebug.el"))
  • Автодополнение кода и документация

    По большей части я использую дефолтный Completion Buffer и Corfu

    (when (package-loaded? "corfu")
      (progn
        (setq corfu-preview-current 'nil)
        (corfu-mode 1)
        (defun show-default-completion-buffer ()
    	(interactive)
    	(corfu-quit)
    	(corfu-mode -1)
    	(completion-at-point)
    	(corfu-mode 1))
        (define-key corfu-map (kbd "M-TAB") 'show-default-completion-buffer)
        (define-key corfu-map (kbd "TAB") 'show-default-completion-buffer)
        (define-key corfu-map (kbd "C-M-i") 'show-default-completion-buffer)      
        (corfu-mode -1)
        (add-hook 'prog-mode-hook 'corfu-mode)))
    
    (when (package-loaded? "corfu-doc")
      (progn
        (add-hook 'prog-mode-hook 'corfu-doc-mode)))
    
  • Модификация дефолта
    (setq completion-styles '(basic partial-completion substring flex emacs22)
          completion-ignore-case t
          read-buffer-completion-ignore-case t
          read-file-name-completion-ignore-case t)
    
  • Агрессивный дефолтный комплит
    (setq aggressive-completion-delay 0.5)
    (aggressive-completion-mode t)
    
  • HELM (не используется)
    (load "helm-autoloads")
    
    (setq helm-completion-style 'emacs
          helm-no-header t)
    
    (global-set-key (kbd "M-x")     #'helm-M-x)
    (global-set-key (kbd "C-x r b") #'helm-filtered-bookmarks)
    (global-set-key (kbd "C-x C-f") #'helm-find-files)
    (global-set-key (kbd "C-x C-b") #'helm-buffers-list)
    (global-set-key (kbd "C-s")     #'helm-occur)
    (global-set-key (kbd "M-y")     #'helm-show-kill-ring)
    (global-set-key (kbd "C-x b")   #'helm-mini)
    
    (define-key helm-map (kbd "<tab>") 'helm-execute-persistent-action)
    (define-key helm-map (kbd "C-i")   'helm-execute-persistent-action)
    (define-key helm-map (kbd "C-z")   'helm-select-action)
    (define-key minibuffer-local-map (kbd "C-c C-l") 'helm-minibuffer-history)
    
    (setq helm-display-header-line          nil
          helm-split-window-in-side-p       t
          helm-echo-input-in-header-line    t
          helm-display-source-at-screen-top nil
          helm-autoresize-max-height        50
          helm-autoresize-min-height        5)
    
    (helm-adaptive-mode)
    (helm-autoresize-mode 1)
    
    (add-hook 'eshell-mode-hook
    	  (lambda ()
    	    (eshell-cmpl-initialize)
    	    (define-key eshell-mode-map (kbd "C-c C-l")  'helm-eshell-history)
    	    (define-key eshell-mode-map [remap eshell-pcomplete] 'helm-esh-pcomplete)
    	    (define-key eshell-mode-map (kbd "M-p") 'helm-eshell-history)))
    
    (add-hook 'eshell-mode-hook
    	  (lambda ()
    	    (define-key eshell-mode-map
    	      (kbd "M-p")
    	      'helm-eshell-history)))
    
    (defun pcomplete/sudo ()
      (let ((prec (pcomplete-arg 'last -1)))
        (cond ((string= "sudo" prec)
    	   (while (pcomplete-here*
    		   (funcall pcomplete-command-completion-function)
    		   (pcomplete-arg 'last) t))))))
    
    (helm-mode 1)
    
    

Полнотекстовый поиск

Для выхода из поиска – C-c C-q

(load "deft-autoloads")

(define-key global-map
  (kbd "C-c n s") 'deft)

(setq deft-recursive t
      deft-use-filter-string-for-filename t
      deft-default-extension "org md"
      deft-directory "~/Documents/Notes")

Визуализирование откатов

При помощи пакета undo-tree

(when (package-loaded? "undo-tree")
  (progn
    (add-hook 'prog-mode-hook #'undo-tree-mode)
    (setq undo-tree-auto-save-history nil)))

Сниппеты

(when (package-loaded? "yasnippet")
  (progn
    (add-hook 'prog-mode-hook #'yas-minor-mode)))

Клиент LSP

(when (package-loaded? "lsp-mode")
  (progn
    (define-key prog-mode-map (kbd "C-c h") 'eldoc)
    ;; (define-key prog-mode-map (kbd "M-<tab>") 'completion-at-point)
    (define-key prog-mode-map (kbd "<f6>") 'xref-find-definitions)

    (add-hook 'php-mode-hook 'lsp)
    (add-hook 'c-mode-hook 'lsp-mode)
    (add-hook 'c++-mode-hook 'lsp-mode)))

Линтеры

;;(add-hook 'php-mode-hook 'flymake-php-load)
;; (add-hook 'php-mode-hook 'flymake-phpstan-turn-on)p
;;(add-hook 'php-mode-hook 'flymake-phpcs-load)

;;(add-to-list 'auto-mode-alist '("\\.\\(php\\|phtml\\)\\'" . phps-mode))

;; (phps-mode-flycheck-setup)

;; (setq phps-mode-async-process t)
;; (setq phps-mode-async-process-using-async-el t)

Выделение

(when (package-loaded? "expand-region")
  (global-set-key (kbd "C-=") 'er/expand-region))

Сессия

(desktop-save-mode 1)

Скроллинг

(setq scroll-margin 0)

Поиск

  • Isearch
    (with-eval-after-load 'isearch
      (define-key isearch-mode-map "\C-h" 'isearch-delete-char)
      (define-key isearch-mode-map "\C-ch" 'isearch-help-for-help))
    
  • Подсчёт кандидатов
    (global-anzu-mode t)
    
  • Swiper (не используется)
    (load "swiper-autoloads")
    (global-set-key (kbd "C-s") 'swiper)
    
    (setq swiper-include-line-number-in-search t
          swiper-use-visual-line t
          swiper-stay-on-quit t)
    

Подсказка биндов

Пакет Which-key

(load "which-key-autoloads")
(which-key-setup-side-window-right)
(which-key-mode)

(setq which-key-side-window-max-width 0.5
      which-key-show-remaining-keys t
      which-key-max-display-columns 50
      which-key-max-description-length 35
      which-key-sort-order 'which-key-local-then-key-order
      which-key-idle-delay 0.25)

Права суперпользователя

Sudo-edit

(package-loaded? "sudo-edit")

Языки программирования

Common Lisp

  • REPL
    (load "sly-autoloads")
    
    (setq sly-lisp-implementations
          '((clisp ("clisp"))
    	(cmucl ("cmucl" "-quiet"))
    	(sbcl ("/opt/sbcl/bin/sbcl") :coding-system utf-8-unix)))
    
    

Erlang

(load "erlang-autoloads")

Ruby

(when (package-loaded? "inf-ruby")
  (add-hook 'ruby-mode-hook 'inf-ruby-minor-mode))

(when (package-loaded? "inf-ruby")
  (add-hook 'ruby-mode-hook 'robe-mode))

Scheme

;; (setq geiser-active-implementations '("guile"))

Python

  • Автодополнение и линт
    (when (package-loaded? "anaconda-mode")
      (progn
        (add-hook 'python-mode-hook 'anaconda-mode)
        (add-hook 'python-mode-hook 'anaconda-eldoc-mode)))
    
    ;; (when (load "flymake" t)
    ;;   (defun flymake-pylint-init ()
    ;;     (let* ((temp-file (flymake-init-create-temp-buffer-copy
    ;; 		       'flymake-create-temp-inplace))
    ;; 	   (local-file (file-relative-name
    ;; 			temp-file
    ;; 			(file-name-directory buffer-file-name))))
    ;;       (list "epylint" (list local-file))))
    
    ;;   (add-to-list 'flymake-allowed-file-name-masks
    ;; 	       '("\\.py\\'" flymake-pylint-init)))
    
    ;; (add-hook 'python-mode-hook 'flymake-mode)
    
  • Прыжки в функции стандартной библиотеки на си

SML

(add-hook 'sml-mode-hook 'sml-mode)

PHP

  • PHP-Mode

    Не осуждайте. Необходимо скачать и распаковать мануал PHP (в формате html) в директорию ~/.emacs.d/php-manual/.

    ;; (add-to-list 'load-path "~/.emacs.d/site-lisp/realgud-xdebug/")
    ;; (require 'realgud-xdebug)
    
    (when (package-loaded? "php-mode")
      (progn
        (add-hook 'php-mode-hook 'php-enable-symfony2-coding-style)
        ;; (setq lsp-intelephense-php-version "7.4.26")
        (setq lsp-intelephense-php-version "8.1.6")
        ;; (defvar phpactor-executable "~/.bin/phpactor")
    
        (add-hook 'php-mode-hook 
    	      '(lambda ()
    		 (require 'yasnippet)
    		 (require 'yasnippet-snippets)
    		 (yas-minor-mode t)
    		 (define-key php-mode-map (kbd "C-c h") 'php-quickhelp-at-point)))
    
        (setq php-manual-path
    	  "~/.emacs.d/php-manual/"
    	  php-quickhelp-dir "~/.emacs.d/php-manual/"
    	  php-quickhelp--dest "~/.emacs.d/php-manual/php_manual_en.json")
    
    
        ;; (add-hook 'php-mode-hook 
        ;; 		'(lambda ()
        ;; 		   ;; (auto-complete-mode t)
    
        ;; 		   ;; (require 'ac-php)
        ;; 		   (require 'php-quickhelp)
        ;; 		   (require 'company)
        ;; 		   (company-mode t)
        ;; 		   (require 'company-php)
        ;; 		   (require 'company-quickhelp)
    
        ;; 		   (require 'yasnippet)
        ;; 		   (require 'yasnippet-snippets)
    
        ;; 		   (set (make-local-variable 'company-backends)
        ;; 			'((company-ac-php-backend company-dabbrev-code)
        ;; 			  php-quickhelp-company-php
        ;; 			  company-capf company-files))
    
        ;; 		   (company-quickhelp-mode t)
    
        ;; 		   (define-key php-mode-map (kbd "C-M-i") 'company-complete)
        ;; 		   (define-key company-mode-map (kbd "M-TAB") 'company-complete)
    
        ;; 		   ;; (setq ac-sources '(ac-source-php php-quickhelp-company-php))
        ;; 		   ;; (setq eldoc-documentation-function
        ;; 		   ;;       'php-quickhelp-eldoc-func)
    
        ;; 		   (yas-minor-mode t)
    
        ;; 		   ;; (define-key php-mode-map (kbd "C-M-i") 'auto-complete)
        ;; 		   ;; (define-key ac-mode-map (kbd "M-TAB") 'auto-complete)
    
        ;; 		   (define-key php-mode-map (kbd "C-c H")
        ;; 			       'php-local-manual-search)
    
        ;; 		   (define-key php-mode-map (kbd "C-c h") 'php-quickhelp-at-point)
        ;; 		   (define-key company-mode-map (kbd "C-c h") 'php-quickhelp-at-point)
    
        ;; 		   ;; (define-key php-mode-map (kbd "C-c t") 'ac-php-show-tip)
    
        ;; 		   ;; Jump to definition (optional)
        ;; 		   (define-key php-mode-map
        ;; 			       (kbd "M-.") 'ac-php-find-symbol-at-point)
    
        ;; 		   ;; Return back (optional)
        ;; 		   (define-key php-mode-map
        ;; 			       (kbd "M-,") 'ac-php-location-stack-back)))
        ))
    
  • Composer
  • Flymake PHP
  • REPL
  • LSP сервер

    PHPactor

    (with-eval-after-load 'php-mode
      (define-key php-mode-map (kbd "M-.") #'phpactor-goto-definition)
      (define-key php-mode-map (kbd "M-?") #'phpactor-find-references))
    
  • Transient меню
    (require 'transient)
    (define-transient-command php-menu ()
      "Php"
      [["Class"
        ("cc" "Copy" phpactor-copy-class)
        ("cn" "New" phpactor-create-new-class)
        ("cr" "Move" phpactor-move-class)
        ("ci" "Inflect" phpactor-inflect-class)
        ("n"  "Namespace" phpactor-fix-namespace)]
       ["Properties"
        ("a"  "Accessor" phpactor-generate-accessors)
        ("pc" "Constructor" phpactor-complete-constructor)
        ("pm" "Add missing props" phpactor-complete-properties)
        ("r" "Rename var locally" phpactor-rename-variable-local)
        ("R" "Rename var in file" phpactor-rename-variable-file)]
      ["Extract"
        ("ec" "constant" phpactor-extract-constant)
        ("ee" "expression" phpactor-extract-expression)
        ("em"  "method" phpactor-extract-method)]
      ["Methods"
        ("i" "Implement Contracts" phpactor-implement-contracts)
        ("m"  "Generate method" phpactor-generate-method)]
      ["Navigate"
        ("x" "List refs" phpactor-list-references)
        ("X" "Replace refs" phpactor-replace-references)
        ("."  "Goto def" phpactor-goto-definition)]
      ["Phpactor"
        ("s" "Status" phpactor-status)
        ("u" "Install" phpactor-install-or-update)]])
    
  • Интеграция с Semantic и EDE
    
    

Языки декларирования

SQL

;; Empty for now (was using emacsql)

Веб шаблоны

  • Web-mode
    (when (package-loaded? "web-mode")
      (progn
    
        (add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode))
        (add-to-list 'auto-mode-alist '("\\.twig.html\\'" . web-mode))
    
        (setq web-mode-markup-indent-offset 2)
        (setq web-mode-enable-auto-pairing t)
        (setq web-mode-enable-css-colorization t)
        (setq web-mode-enable-block-face t)
        (setq web-mode-enable-current-element-highlight t)
        (setq web-mode-enable-current-column-highlight t)))
    

Org

  • Org-mode
    (org-babel-do-load-languages
     'org-babel-load-languages
     '((R . t)
       (ditaa . t)
       (dot . t)
       ;; (php . t)
       (emacs-lisp . t)
       (gnuplot . t)
       (haskell . nil)
       (latex . t)
       ;;(ledger . t)
       (ocaml . nil)
       (octave . t)
       (python . t)
       (ruby . t)
       (screen . nil)
       (shell . t)
       (sql . nil)
       (sqlite . nil)))
    
    (global-set-key (kbd "C-c l") 'org-store-link)
    (global-set-key (kbd "C-c a") 'org-agenda)
    (global-set-key (kbd "C-c c") 'org-capture)
    ;; (global-set-key (kbd "M-f") 'org-metaright)
    ;; (global-set-key (kbd "M-b") 'org-metaleft)
    ;; (global-set-key (kbd "M-p") 'org-metaup)
    ;; (global-set-key (kbd "M-n") 'org-metadown)
    
    (setq org-default-notes-file "~/Documents/life.org"
          org-use-speed-commands t
          org-adapt-indentation nil
          org-return-follows-link t
          org-display-remote-inline-images 'download
          org-image-actual-width (list 400)
          org-hide-emphasis-markers t
          org-outline-path-complete-in-steps nil
          org-src-tab-acts-natively t
          org-confirm-babel-evaluate nil)
    
    (setq org-todo-keywords
          (quote ((sequence "TODO(t)"
    			"MIGRATE(m)" "|"
    			"IN PROGRESS(p)" 
    			"DONE(d)")
    	      (sequence "WAITING(w@/!)"
    			"HOLD(h@/!)" "|"
    			"CANCELLED(c@/!)"
    			"PHONE"
    			"MEETING"))))
    (setq org-todo-keyword-faces
          (quote (("TODO" :foreground "red" :weight bold)
    	      ("NEXT" :foreground "blue" :weight bold)
    	      ("DONE" :foreground "forest green" :weight bold)
    	      ("WAITING" :foreground "orange" :weight bold)
    	      ("HOLD" :foreground "magenta" :weight bold)
    	      ("CANCELLED" :foreground "forest green" :weight bold)
    	      ("MEETING" :foreground "forest cyan" :weight bold)
    	      ("PHONE" :foreground "blue" :weight bold))))
    
  • Org-ref (не используется)
    (load "org-ref-autoloads")
    
    (setq reftex-default-bibliography '("~/Documents/bibliography/references.bib"))
    
    ;; see org-ref for use of these variables
    (setq org-ref-bibliography-notes "~/Documents/bibliography/notes.org"
          org-ref-default-bibliography '("~/Documents/Bibliography/references.bib")
          org-ref-pdf-directory "~/Documents/bibliography/bibtex-pdfs/")
    
  • Org-roam
    (when (package-loaded? "org-roam")
      (progn
        (setq org-roam-directory (file-truename "~/Documents/Notes")
    	  org-roam-graph-viewer "icecat"
    	  org-roam-v2-ack t
    	  org-roam-completion-everywhere t
    	  org-roam-index-file (concat org-roam-directory "/20210409054712-жизнь.org"))
    
        ;; (load "org-roam-ui-autoloads")
        ;; (org-roam-db-sync)
    
        (org-roam-db-autosync-mode t)
    
        (defun org-roam-jump-to-index ()
          "Stub of recreating the function from V1"
          (interactive)
          (let
    	  ((org-roam-index org-roam-index-file))
    	(find-file org-roam-index)))
    
        (define-key global-map
          (kbd "C-c n l") 'org-roam-node-insert)
        (define-key global-map
          (kbd "C-c n f") 'org-roam-node-find)
        (define-key global-map
          (kbd "C-c n b") 'org-roam-buffer-toggle)
        (define-key global-map
          (kbd "C-c n t t") 'org-roam-tag-add)
        (define-key global-map
          (kbd "C-c n t r") 'org-roam-tag-remove)
        (define-key global-map
          (kbd "C-c n i") 'org-roam-jump-to-index)
        (define-key global-map
          (kbd "C-c n g") 'org-roam-graph)
        (define-key global-map
          (kbd "C-c n d") 'org-roam-db-build-cache)
        (define-key global-map
          (kbd "C-c n r") 'org-roam-node-random)
        (define-key global-map  
          (kbd "C-c n j") 'org-roam-dailies-find-date)))
    
  • Агенда
    (add-to-list 'org-agenda-files
    	     "~/Documents/Notes/20210422181951-ежедневная_рутина.org")
    (add-to-list 'org-agenda-files
    	     "~/Documents/Notes/20210409072648-дела.org")
    

YAML

(package-loaded? "yaml-mode")

Коммуникации

Telega

(when (package-loaded? "telega")
  (setq telega-filter-custom-show-folders t
	telega-chat-fill-column 40
	telega-root-fill-column 60
	telega-url-shorten-use-images t)

  (define-key global-map (kbd "C-c t") telega-prefix-map))

Mastodon

(when (package-loaded? "mastodon")
  (setq mastodon-active-user "w96k"
	mastodon-instance-url "https://fosstodon.org/"))

Наука

Разное

Минорные твики дефолтного имакса

  • Подсвечивать текущую строку
    (global-hl-line-mode 1)
    
  • Открывать список буферов в отдельном фрейме
    (add-to-list 'special-display-buffer-names "*Buffer List*")
    (setq Buffer-menu-files-only t)
    
  • Автодополнение в echo при M-x и других командах
    (icomplete-mode 1)
    
  • Проверять орфографию
    (flyspell-mode 1)
    
  • Удалять регионы при нажатии backspace
    ;; It is lagging for some reason
    (delete-selection-mode 0)
    
  • Не спрашивать о несуществующих буферах
    (setq-default confirm-nonexistent-file-or-buffer t)
    
  • Переключение буферов
    (global-set-key (kbd "M-o")  'mode-line-other-buffer)
    
  • Минорные твики
    (setq redisplay-dont-pause t)
    
    (setq select-enable-clipboard t
          select-enable-primary t)
    
    (setq completions-detailed nil)
    
    (setq kill-buffer-delete-auto-save-files t)
    (setq next-error-message-highlight t)
    
    (setq mode-line-compact 'long)
    
    (setq completions-group t)
    
    ;;(set-frame-parameter nil 'internal-border-width 0)
    
    ;; (set-window-buffer nil (current-buffer))
    
      (setq default-directory "~/"
          delete-seleciton-mode t
          inhibit-startup-message t
          initial-scratch-message nil
          custom-safe-themes t
          delete-old-versions t
          confirm-kill-processes nil
          enable-local-variables t)
    
  • Shell
    (setq ansi-color-for-comint-mode t)
    (setq shell-command-prompt-show-cwd t)
    
  • Переменная PATH в eshell
    (setq exec-path-from-shell-variables
          '("PATH" "MANPATH"))
    
    (when (and (memq window-system '(mac ns x))
    	   (not (eq system-type 'berkeley-unix)))
      (exec-path-from-shell-initialize))
    
  • Отображение номера колонки
    (column-number-mode)
    
  • nobreak символы
    (setq nobreak-char-display nil)
    
  • Меню

    По неизвестным причинам навигация в меню при помощи биндов Emacs не работает

    ;; GTK menu doesn't allow emacs-style navigation
    (define-key global-map (kbd "<f10>") 'tmm-menubar)
    
  • Сохранять временные файлы не в той же директории
    (defvar backup-dir "~/.emacs.d/backups/")
    
    (setq
     backup-by-copying t
     backup-directory-alist
     '(("." . "~/.emacs.d/backups/"))
     version-control nil)
    
  • Календарь

    Делаем начало недели в понедельник.

    (setq calendar-week-start-day 1)
    
  • Вернуться в предыдущий буфер
    (define-key global-map (kbd "C-q C-q") 'previous-buffer)
    (define-key global-map (kbd "C-S-q C-S-q") 'next-buffer)
    
  • Смена раскладки (EN / RU) и поддержка биндов на других языках

    Работает на C-\

    (set-input-method "russian-computer")
    (toggle-input-method)
    
  • Требовать создания последней пустой строки
    (setq require-final-newline t)
    
  • Стирать текст на C-h как в Bash

    И переназначаем старые бинды

    (define-key global-map (kbd "C-h") 'delete-backward-char)
    (define-key global-map (kbd "C-c h") 'help-command)
    
  • Поддержка CamelCase в навигации
    (global-subword-mode 1)
    
  • Kills
    (define-key global-map (kbd "C-k") 'kill-region)
    (define-key global-map (kbd "C-w") 'backward-kill-word)
    

Браузер

(add-hook 'eww-mode-hook
	  (lambda ()
	    (set-fill-column 80)
	    (display-fill-column-indicator-mode)
	    (visual-fill-column-mode)))

Tramp

(add-to-list 'tramp-remote-path 'tramp-own-remote-path)

Docker

(package-loaded? "docker")
(package-loaded? "docker-compose-mode")

Debian

Инструменты для работы с пакетным менеджером Debian'а apt'ом и смежными инструментами.

(load "debian-el-autoloads")
(load "dpkg-dev-el-autoloads")

Guix

(package-loaded? "geiser-guile")

(package-loaded? "guix")

(setq geiser-guile-binary "guile")

(with-eval-after-load 'geiser-guile
  (progn
  (add-to-list 'geiser-guile-load-path "~/projects/guix/")))

(load-file "~/projects/guix/etc/copyright.el")

(setq copyright-names-regexp
      (format "%s <%s>" user-full-name user-mail-address))

Nix

(package-loaded? "nix")

Vim

(add-to-list 'auto-mode-alist '("\\.vim\\(rc\\)?\\'" . vimrc-mode))

Direnv

(when (package-loaded? "direnv")
    (direnv-mode))

Баг-трекеры

  • Debbugs

PDF

Увеличение/уменьшение шрифта

(defun zoom-in ()
  (interactive)
  (let ((x (+ (face-attribute 'default :height)
	      10)))
    (set-face-attribute 'default nil :height x)
    (set-face-attribute 'mode-line nil :height x)
    (set-face-attribute 'mode-line-inactive nil :height x)
    (set-face-attribute 'mode-line-position-face nil :height x)))

(defun zoom-out ()
  (interactive)
  (let ((x (- (face-attribute 'default :height)
	      10)))
    (set-face-attribute 'default nil :height x)
    (set-face-attribute 'mode-line nil :height x)
    (set-face-attribute 'mode-line-inactive nil :height x)
    (set-face-attribute 'mode-line-position-face nil :height x)))

(define-key global-map (kbd "C-=") 'zoom-in)
(define-key global-map (kbd "C-+") 'zoom-out)

Автокомплит у yes-or-no

Фуллскрин

Отображать ровно столько строчек, сколько вмещает экран.

Не работает с native-comp.

(toggle-frame-fullscreen)

(defun fullscreen ()
"Fullscreen."
(interactive)
(x-send-client-message nil 0 nil "_NET_WM_STATE" 32
		       ;; if first parameter is '1', can't toggle fullscreen status
		       '(1 "_NET_WM_STATE_FULLSCREEN" 0)))

Заменять доллар на символ рубля

Очень важно

(push '("$" . ?₽) prettify-symbols-alist)
(global-prettify-symbols-mode 1)

w96k © 2019-2022

License

2022-08-29 Пн 00:21