Статья написана под впечатлением от статьи Emacs Flaw: Simple Changes Emacs Should Adopt, написанной широко известным в узких кругах Emacs-троллем и автором множества пакетов Xah Lee. Кстати, он один из противников тотального внедрения HTTPS, поэтому статья по ссылке доступна только по HTTP.
Итак, как же нам улучшить Emacs?
Терминология
В Emacs полно устаревшей терминологии. Новичкам было бы значительно проще, если бы вместо frames (фреймы) и windows (окна) соответствующие сущности назывались windows (окна) и panels (панели). Эту идею больше 10 лет назад высказал ещё сам RMS в надежде на то, что терминология будет осовременена в ближайшее время:
Conceivably we could rename "window" to "pane" and "frame" to "window". I think the two renamings would have to be done in two different releases, perhaps a year or two apart.
Whether it is worth the trouble, I don't know.
--
Dr Richard Stallman
President, Free Software Foundation
51 Franklin St
Boston MA 02110
USA
www.fsf.org www.gnu.org
Это было написано 6 января 2014 года. С тех пор ничего не изменилось. Просто запомните:
frame это окно, созданное ОС;
window это панель внутри фрейма.
Основная сущность Emacs называется буфером (buffer). В IT это слово уже давно приобрело собственное значение: область для промежуточного хранения данных. Если по сути, то название buffer в Emacs этому определению не противоречит. Другое дело, что файловый буфер в Emacs это не то же самое что файловый буфер в современных ОС. То, что под этим термином понимают в Emacs -- это просто файл, открытый в редакторе.
Клавиши в Emacs, как и в 1980-х, называются Control, Meta, Super и Hyper. На современных клавиатурах вы не найдёте Meta, Super и Hyper, а Control не тот, что на клавиатурах Lisp-машин.
На современных клавиатурах вместо Meta стоит Alt. Проблема в том, что Meta и Ctrl на клавиатурах Lisp-машин находились там, где сейчас находятся Ctrl и Alt. Это делает команды Emacs неудобными, потому что вместо нажатия Alt большим пальцем мы вынуждены ломать мизинец об Ctrl.
Клавиши местами поменяли, а сочетания переделать забыли, с кем не бывает? Программисты накосячили, скоро исправят. Ведь исправят же?

Scratch и initial-buffer
Буфер *scratch* вряд ли вам понадобится, если только вы не программист на Emacs Lisp. Однако, по какой-то странной причине Emacs создаёт его при каждом запуске. Чтобы предотвратить это, добавьте в init.elкод:
;; Буфер *scratch* не нужен, если вы не программист Emacs Lisp
(defun init-kill-scratch ()
"Закрыть буфер *scratch* при запуске редактора или подключении клиента."
(when (get-buffer "*scratch*")
(kill-buffer "*scratch*")))
(add-hook 'after-init-hook 'init-kill-scratch)
(add-hook 'server-after-make-frame-hook 'init-kill-scratch)А ещё при запуске Emacs показывает стартовую страницу с информацией о себе. Молодец. Первое, что делает большинство пользователей при запуске любого редактора или IDE -- эту страницу отключают. В Emacs надо делать всё самому:
(setopt inhibit-startup-screen t)Задам наводящий вопрос: почему бы не сделать это поведением по умолчанию?
Сессии
Emacs умеет сохранять своё состояние между сессиями (запусками), а именно:
список открытых файлов;
список посещённых файлов;
состояние фреймов и окон;
позицию курсора в посещённых файлах;
историю команд, введённых в minibuffer.
По какой-то непонятной причине по умолчанию всё это выключено.

Иначе как осознанным вредительством это считать нельзя, ведь практически любой современный редактор делает это всё без дополнительных настроек. А вам нужно добавить в init.el код, чтобы получить то же самое:
;; 📦 DESKTOP
;; Сохранение состояния Emacs между сессиями.
;; https://www.gnu.org/software/emacs/manual/html_node/emacs/Saving-Emacs-Sessions.html
(use-package desktop
:custom
(desktop-dirname user-emacs-directory "Каталог для хранения файла .desktop.")
(desktop-load-locked-desktop t "Загрузка файла .desktop даже если он заблокирован.")
(desktop-restore-frames t "Восстанавливать фреймы.")
(desktop-save t "Сохранять список открытых буферов, файлов и т. д. без лишних вопросов.")
:config
(desktop-save-mode t)
(add-to-list 'delete-frame-functions 'desktop-save)
(add-to-list 'desktop-modes-not-to-save 'dired-mode)
:hook
(after-init . desktop-read)
(server-after-make-frame . desktop-read)
(kill-emacs . (lambda () (desktop-save user-emacs-directory t)))
(server-done . desktop-save))
;; 📦 RECENTF-MODE
;; Список последних открытых файлов.
(use-package recentf
:custom
(recentf-max-saved-items 100 "Помнить последние 100 файлов")
(recentf-save-file (locate-user-emacs-file "recentf") "Хранить список в файле .emacs.d/recentf")
:config (recentf-mode t))
;; 📦 SAVEPLACE
;; Запоминание позиции курсора в посещённых файлах.
(use-package saveplace
:custom
(save-place-forget-unreadable-files t "Не запоминать положение в нечитаемых файлах.")
:config
(save-place-mode t))
;; 📦 SAVEHIST
;; Запоминание истории команд.
(use-package savehist
:hook
(server-done . savehist-save)
(kill-emacs . savehist-save)
:config
(add-to-list 'delete-frame-functions 'savehist-save)
(savehist-mode t))
Удаление выделенного текста
Emacs не модальный редактор, в отличие от VIM, NeoVim и Helix. Т. е. для ввода текста не нужно менять режим, достаточно начать нажимать на клавиши. Однако, поведение Emacs при работе с выделенным текстом по умолчанию отличается от того, к чему нас всех приучили современные ОС.
Допустим, мы выделили текст любым удобным способом. В любом нормальном редакторе, IDE или поле ввода, созданном ОС, поведение стандартизировано:
Клавиша | Действие |
Del | Удалить выделенный текст |
BackSpace | Удалить выделенный текст |
Алфавитно-цифровые клавиши | Удалить выделенный текст, вставить новый знак в позиции курсора |
Но Emacs не такой как все:
Клавиша | Действие |
Del | Удалить знак справа от курсора |
BackSpace | Удалить знак слева от курсора |
Алфавитно-цифровые клавиши | Вставить новый знак в позиции курсора |
Почему бы не привести настройки Emacs к современным стандартам? Добавим три строки кода и одну строку комментария в init.el:
;; 📦 DELSEL
(use-package delsel
:config
(delete-selection-mode t)) ;; Удалять выделенный фрагмент при вводе текстаНужный режим в Emacs есть, просто по непонятной причине выключен!
Внешний вид курсора
В современных редакторах курсор имеет вид мерцающей вертикальной черты. Мне кажется это хорошей иллюстрацией понятия "аффорданс": внешний вид курсора наглядно показывает, куда будет вставлен новый текст, не нужно гадать, всё самоочевидно.
Но в Emacs по умолчанию используется прямоугольник, даже если дело происходит в GUI. Неужели этот код такой сложный?
(setopt cursor-type 'bar)Ну, окей, допустим, надо определить, где мы находимся, а то вдруг в терминале работаем:
(when (display-graphics-p (selected-frame))
(setopt cursor-type 'bar))Не выглядит как задача на 34 Story Point, правда?
Ответы на вопросы
По умолчанию для ответов на вопросы Emacs требует ввода слов yes и no. Уточню, что мы сейчас рассматриваем случай, когда использование UI выключено или невозможно (например, в терминалах). Удивительно, но в Emacs по умолчанию НЕ сделаны эти настройки:
(setopt use-short-answers t) ;; Новые версии
(defalias 'yes-or-no-p 'y-or-n-p) ;; Старые версииПищание
Знаете, что меня бесит в настройках по умолчанию? Пищание! Emacs пищит всякий раз, когда вы пытаетесь сделать что-то не так:
прокрутить содержимое вниз, находясь в конце файла;
перейти в другое окно, когда активен минибуфер;
и многое, многое другое!
Тут Emacs вам не помогает, а пугает своим писком. Можно ли его отключить, не используя сторонние пакеты? Вы знаете ответ.
(setopt ring-bell-function 'ignore ;; Заменим писк ничегонеделанием
visible-bell t) ;; Лучше мигать чем пищатьСовременные экраны
Emacs умеет плавно прокручивать текст. Режим pixel-scroll-precision-mode добавили ещё в версии 29.1. Однако он по умолчанию выключен.
;; 📦 PIXEL-SCROLL
;; Плавная прокрутка текста
(when (package-installed-p 'pixel-scroll)
(use-package pixel-scroll
:config
(pixel-scroll-mode t)
(pixel-scroll-precision-mode)))
;; 📦 FRAME
;; Управление фреймами.
(use-package frame
:custom
(frame-resize-pixelwise t "Размер фреймов считать по пикселям а не по символам"))Уж казалось бы, что проще: просто при запуске проверь наличие возможности и включи её! Однако, Emacs зачем-то заставляет пользователей самих писать этот код.
Удаление файлов
Зато с удаленим файлов всё в порядке! "Корзина не нужна" -- решили авторы Emacs, поэтому вызов операций удаления файлов приводит к их стиранию с диска, а не перемещению в корзину.
Не вижу ни одной причины, по которой не следовало бы сделать настройку delete-by-moving-to-trash включённой по умолчанию:
(setopt delete-by-moving-to-trash t)C-z
Напоследок расскажу о поведении Emacs, от которого у меня отвалилась жопа. По умолчании при нажатии [Ctrl+Z] он не отменяет последнюю операцию, а сворачивается на панель задач в графическом режиме и уходит в фон в TUI. Уж казалось бы, сколько лет прошло! Можно ведь повесить undo на [Ctrl+Z]? Можно:
;; Изменим некоторые привязки клавиш по умолчанию
(require 'keymap)
(keymap-global-unset "C-z") ;; Такой Ctrl+Z нам не нужен
(use-package simple
:bind (:map global-map
("C-z" . undo)))Итоги
Я не настолько хорош, чтобы коммитить в master Emacs'а. Однако, я достаточно хорош, чтобы создать репозиторий "Emacs From Scratch": шаблон init.el, с которого можно начать писать свой собственный конфиг.
