GNU EMACS для технических писателей


Channel's geo and language: not specified, not specified
Category: not specified


Настройка, использование, хаки

Related channels

Channel's geo and language
not specified, not specified
Category
not specified
Statistics
Posts filter


Тем, кто работает с Terraform, может быть полезен пакет terraform-mode. По умолчанию он не добавляет во Flycheck нужный способ проверки кода, но это легко исправить:

(require 'terraform-mode)
(defun setup-terraform-mode ()
"Настройка `terraform-mode`."
(setq-default flycheck-checker 'terraform))
(add-to-list 'auto-mode-alist (cons "\\.tf$" 'terraform-mode))
(add-hook 'terraform-mode-hook #'setup-terraform-mode)

Страница проекта: https://github.com/emacsorphanage/terraform-mode


В EMACS есть специальная функция, возвращающая true, если существует другая функция, имя которой передано как аргумент. Это может быть полезно в тех случаях, когда EMACS используется на нескольких компьютерах. Например, в EMACS для терминала не получится выключить панель с кнопками просто потому, что он собран без поддержки GTK, и такую функцию он в принципе не поддерживает.
Хочется иметь один универсальный init.el, а не 10, под каждую конфигурацию, версию, опции компиляции и т. д. В этом случае и приходит на помощь fboundp():
(when (fboundp 'tool-bar-mode)
(tool-bar-mode -1))




В EMACS 29 будет встроенная поддержка use-package. Это хорошее средство для управления конфигурацией редактора в декларативном стиле.


Если вы уже какое-то время вносите правки в свой init.el, скорее всего, у вас уже появился вопрос о различиях между when, unless, if и cond.

TL;DR: первые два оператора — макросы над if.

Оператор when используется, когда мы обрабатываем только случай выполнения условия. На JavaScript это выглядело бы так:

if (условие) {
действия;
}

На EMACS Lisp:

(when (условие)
(действия))

Оператор unless используется, напротив, когда условие не выполняется:

if (!условие) {
действия;
}

На EMACS Lisp:

(unless (условие, которое не должно выполняться)
(действия))

Хороший пример — создание каталога в случае его отсутствия:

(unless (file-directory-p )
(make-directory t))

Оператор if дает возможность обработать 2 случая: условие выполняется и условие не выполняется:

if (условие) {
действия_в_случае_успеха;
} else {
действия_в_противном_случае;
}

На EMACS Lisp:

(if (условие)
(действия_при_выполнении_условия)
(действия_в_противном_случае))

Теперь разберём cond. Его ближайший аналог — оператор case. В общем виде выглядит так:

(cond
((условие 1) (действия))
((условие 2) (действия))
((условия 3) (действия)))

Выполнение оператора прерывается при первой успешной проверке условия. В примере выше проверка условий 2 и 3 не будет выполнена, если успешно выполнится условие 1.

Чтобы добавить вариант "по умолчанию", когда ни одно условие не выполнилось, нужно добавить конструкцию вида:

(cond
((условие 1) (действия))
((условие 2) (действия))
...
(t (действия по умолчанию)))

#lisp #if #when #unless #cond


В EMACS сочетание клавиш [Ctrl+A] используется не для выделения всего текста, а для перехода в начало строки. Для перехода в конец нужно нажать [Ctrl+E]. За выделение всего содержимого буфера отвечает функция mark-whole-buffer, по умолчанию привязанная к последовательности [Ctrl+x, h].

Если вы привыкли к тому, что [Ctrl+A] выделяет весь текст, привяжите функцию mark-whole-buffer к нужному сочетанию клавиш:

(global-set-key (kbd "C-a") 'mark-whole-buffer)

Но прежде подумайте: что вам на самом деле приходится делать чаще — переходить в начало строки или выделять всё содержимое буфера?


Как быстро поменять регистр символов? Достаточно выбрать нужный текст и нажать:

[Alt+L] — к нижнему регистру.
[Alt+U] — к верхнему регистру.

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

Кстати, нажатие [Ctrl+L] используется для вертикальной прокрутки окна относительно текущей позиции курсора. Если нажать это сочетание несколько раз, содержимое буфера будет прокручиваться таким образом, чтобы строка оказалась:

1. В центре экрана.
2. В верхней части экрана.
3. В нижней части экрана.
4. Снова по центру.


Сегодня поговорим о paragraph-indent-text-mode и его младшем брате paragraph-indent-minor-mode. Допустим, вы набираете текст в text-mode. Некоторые пользователи используют для оформления абзацев отступы в несколько пробелов:

Абзац с отступом

При переходе на новую строку отступ новой строки будет добавлен автоматически:

Абзац с отступом.
Ещё один абзац с отступом.

Вставку пробелов для выравнивания отступом можно отключить, но для этого нужно активировать режим paragraph-indent-text-mode, если в качестве основного режима используется text-mode, и paragraph-indent-minor-mode в противном случае.

Теперь при переходе на новую строку отступ будет удалён у существовавшей строки и не будет добавляться к новой.


Чтобы посмотреть режимы, включенные в активном буфере, нужно нажать [Ctrl+h, m].


Video is unavailable for watching
Show in Telegram


Допустим, нам передали документацию, написанную в Windows с использованием кодировки CP-1251. При открытии файлов EMACS будет показывать кракозябры. Как изменить кодировку, используемую EMACS для отображения загруженного файла?

1. Нажать [Ctrl+x, Enter, r], чтобы выполнить команду revert-buffer-with-coding-system.
2. Ввести имя кодировки, в которой, предположительно, сохранен файл. В рассматриваемом случае будет достаточно ввести «1251», чтобы получить список нужных вариантов. Нужно выбрать нужную кодировку и нажать [Enter].
3. Подтвердить открытие файла с указанной кодировкой: EMACS прочитает файл заново, но с указанной кодировкой.

Пусть теперь нам нужно преобразовать файл в UTF-8.

1. Нажать [Ctrl+x, Enter, f], чтобы выполнить команду set-buffer-file-coding-system.
2. Задать желаемую кодировку указанным выше способом.
3. Нажать [Enter].

Примечание: я в курсе про iconv.

#кодировки #1251


Video is unavailable for watching
Show in Telegram
Типы курсоров в EMACS


В большинстве современных текстовых редакторов курсор имеет вид мигающей вертикальной черты небольшой толщины. EMACS, не смотря на свой возраст, — тоже современный текстовый редактор.
За внешний вид курсора в EMACS отвечает переменная cursor-type, которая может принимать следующие значения:

- bar — тонкая вертикальная линия;
- (bar . ) — вертикальная линия указанной ширины (в пикселах);
- box — залитый цветом вертикальный прямоугольник шириной в один символ;
- hbar — залитый цветом горизонтальный прямоугольник;
- (hbar . ) — залитый цветом горизонтальный прямоугольник указанной высоты;
- hollow — не залитый цветом вертикальный прямоугольник шириной в один символ;
- nil — не показывать курсор;
- t — внешний вид курсора определяется настройками фрейма.

Мне нравится тонкая вертикальная линия, поэтому в моём init.el есть такая строчка:

(setq-default cursor-type 'bar)

#cursor


Автоматическое закрытие скобок — это удобно. В EMACS есть как сторонние, так и встроенные пакеты, реализующие эту функциональность.

electric-pair-mode — встроенный режим, позволяющий автоматически закрывать парные скобки. Например, вы вводите (, а закрывающая скобка ) вставляется автоматически. Одних только скобок и двойных кавычек маловато. Давайте добавим автоматическое закрытие кавычек-ёлочек, а сам режим активируем глобально:

(require 'electric)
(require 'elec-pair)

(add-to-list 'electric-pair-pairs '(?« . ?»))
(add-to-list 'electric-pair-text-pairs '(?« . ?»))

(electric-pair-mode 1)

Если же нужно, чтобы electric-pair-mode работал только в определённых режимах, используйте add-hook и electric-pair-local-mode, например:

(add-hook 'markdown-mode-hook #'electric-pair-local-mode)

#electric


Стартовый экран EMACS не очень полезен, но это легко исправить с помощью пакета dashboard:

1. Установите пакет dashboard любым удобным способом.
2. Добавьте в init.el строки:

;; Dashboard
;; https://github.com/emacs-dashboard/emacs-dashboard
(message "Загрузка пакета dashboard.")
(require 'dashboard)
(setq
dashboard-items
'(
(recents . 15) ; 15 последних открытых файлов
(bookmarks . 5) ; 5 последних добавленных закладок
(projects . 5) ; 5 последних открытых проектов
(registers . 5)) ; 5 последних добавленных регистров
dashboard-set-heading-icons (display-graphic-p) ; Иконка в верхней части дашборда, если режим графический
dashboard-set-file-icons (display-graphic-p)) ; Иконки возле имен файлов, если режим графический
(dashboard-setup-startup-hook) ; Активировать дашборд при запуске EMACS

Здесь:

- recents — последние открытые файлы;
- bookmarks — последние добавленные закладки.
- projects — последние открытые проекты (необходим установленный и настроенный пакет projectile).
- registers — так называемые регистры — временные метки в файле, с помощью которых можно быстро по нему перемещаться без запоминания номеров строк.

Для отображения иконок необходим пакет all-the-icons. Если у вас его ещё нет, обязательно установите.

#dashboard


Xah Lee ещё в 2015-м году выпустил обновление своего поста, в котором писал, как нам обустроить EMACS, чтобы сделать его более дружелюбным к пользователям.
Я решил использовать из этого поста идею, касающуюся документации: вместо требующих обучения [C-x b] или [M-x] писать нормально: [Ctrl+x, b] / [Alt+x].
Все посты в канале будут обновлены для следования новому подходу.


Вам знакома такая проблема, что иногда сложно понять, в каком месте JSON расположен тот или иной параметр? Допустим, вы работаете с очень сложным API, готовым принимать в каждом запросе десятки параметров. Что-то вроде такого, только на несколько страниц в браузере:

{
"clusterId": "string",
"clusterName": "string",
"postgreSQL": {
"version": "string",
"config": {
"databases": ["string"],
"db_config": {
...
}
}
}
}

В итоге вы находите нужный параметр, и теперь надо передать его API, но вы не помните, это postgreSQL.config.databases.restrictions или postgreSQL.config.restrictions. А страница огромная, в браузер не вмещается. Индикаторов вложенности тоже нет.

1. Скопируйте весь огромный JSON в буфер обмена и вставьте в новый буфер EMACS.
1. Удалите из него комментарии, если они там есть. Строка комментария начинается с двух косых черт //.
1. Активируйте json-mode: [Alt+x], json-mode, [Enter].
1. Перейдите на строку с нужным параметром.
1. Вызовите команду json-mode-show-path. Это можно сделать через [Alt+x] или нажатие последовательности комбинаций [Ctrl+c, Ctrl+p].

#emacs #json #path


dired это хорошо, но хочется чего-то более наглядного для работы с файлами. Очень хорошее решение предлагает автор пакета treemacs.

Краткая инструкция по пользованию:

1. Установка

(message "Загрузка пакета treemacs.")
(require 'treemacs)
(setq treemacs-width 30) ;; Ширина окна с файлами
(define-key treemacs-mode-map (kbd "f") 'find-grep) ;; По нажатию будет появляться окно для поиска
(global-set-key (kbd "") 'treemacs) ;; Вкл/выкл отображение дерева
(treemacs-follow-mode 1) ;; При смене буфера показывать файл в дереве
(treemacs-git-mode 'simple) ;; Без всяких сложностей
(treemacs-filewatch-mode 1) ;; Отслеживать состояние файловой системы в реальном времени

При первом запуске Treemacs предложит настроить каталоги. Введите проекты и каталоги в таком формате:

* Ansible
** Ansible
- path :: ~/repo/ansible
* dunaevsky-ms.ru
** dunaevsky-ms.ru
- path :: ~/repo/dunaevsky-ms.ru
* EMACS
** Emacs
- path :: ~/.emacs.d

Чтобы завершить редактирование, нажмите [Ctrl-c, Ctrl-c]. Если ошибок нет, буфер закроется, Treemacs тоже. Вызовите его снова, и он покажет проект, идущий в списке первым.

Прочие комбинации клавиш:
[u] — выйти на уровень вверх
[Ctrl+c, Ctrl+w, e] — редактировать (edit) проекты (то самое окно, что появляется при первом запуске)
[Ctrl+c, Ctrl+w, s] — переключиться (switch) на другой проект (будет выведен список)
[c, d] — создать (create) директорию (directory)
[c, f] — создать (create) файл (file)
[R] — переименовать (rename) элемент под курсором
[r] — обновить (refresh) состояние дерева
[n] — перейти к следующему (next) элементу списка независимо от уровня
[Alt+n] — перейти к следующему элементу списка, расположенному на том же уровне. Полезно, когда открыта куча директорий, и нужно перейти из одной в другую.
[p] — перейти к предыдущему элементу списка независимо от уровня
[Alt+p] — перейти к предыдущему элементу списка, расположенному на том же уровне.
[o, v] — открыть файл под курсором, разделив предыдущий активный буфер по вертикали (будут один под другим)
[o, h] — открыть файл под курсором, разделив предыдущий активный буфер по горизонтали (два буфера будут рядом)
[?] — справка. Там много полезного.

#treemacs


Оказывается, репозиторий gnu уже давно входит в стандартный список репозиториев EMACS, и его можно убрать из package-archives, оставив там только MELPA:

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

Для установки пакетов тоже появились удобные встроенные средства. Список пакетов, которые должны быть установлены, хранится в переменной package-selected-packages из пакета package.el:

(setq
package-selected-packages
'
all-the-icons
dashboard
flycheck
magit
markdown-mode
treemacs)

Установка сейчас тоже делается немного по-другому. Всё-таки, пришлось оставить немного самописного кода, но в целом задачу автоматизировали по максимуму:

(package-initialize)
(defvar packages-refreshed nil "Проверка того, что список пакетов обновлён.")
;; Если хотя бы один из списка не установлен, нужно
;; 1. Обновить список пакетов.
(dolist (pkg package-selected-packages)
(unless (package-installed-p pkg)
(unless packages-refreshed
(progn
(package-refresh-contents)
(setq packages-refreshed 1)))))
;; 2. Установить недостающее.
(if packages-refreshed
(package-install-selected-packages))

#package #emacs #пакеты


Больше не нужен nlinum. Оказывается, в EMACS несколько лет уже как сделали нативное отображение номеров строк. Включается по команде:

(display-line-numbers-mode 1)

Вариант для тотального использования номеров:

(global-display-line-numbers-mode 1)

#nlinum

20 last posts shown.

68

subscribers
Channel statistics