29.18 Атомарные окна

Атомарные окна — это прямоугольные композиции как минимум двух живых окон. Они обладают следующими отличительными характеристиками:

Это означает, что основные группы функций, изменяющих структуру окон, обращаются с атомарным окном как с живым, сохраняя тем самым внутреннюю структуру атомарного окна.

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

Атомарные окна реализованы с помощью зарезервированного параметра окна window-atom (см. Параметры окон) и внутреннего окна (см. Основные понятия об окнах Emacs), называемого корневым окном атомарного окна. Все окна, входящие в одно атомарное окно, имеют это корневое окно своим общим предком и им назначен не-nil параметр window-atom.

Следующая функция возвращает корень атомарного окна, в которое входит указанное окно:

Функция: window-atom-root &optional window

Эта функция возвращает корень атомарного окна, в которое входит window. Указанное window должно быть допустимым окном; по умолчанию это выбранное окно. Возвращает nil, если window не входит в атомарное окно.

Самый простой подход к созданию нового атомарного окна — взять существующее внутреннее окно и применить следующую функцию:

Функция: window-make-atom window

Эта функция преобразует window в атомарное окно. Указанное window должно быть внутренним окном. Всё, что делает эта функция, — устанавливает параметр window-atom для каждого потомка window в t.

Для создания нового атомарного окна из существующего живого окна или для добавления нового окна в существующее атомарное окно можно использовать следующую функцию действия отображения буфера (см. Функции действия для отображения буфера):

Функция: display-buffer-in-atom-window buffer alist

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

Указанный alist — это ассоциативный список символов и значений. Следующие символы имеют специальное значение:

window

Значение такого элемента указывает существующее окно, с которым должно быть объединено новое окно. Если указано внутреннее окно, все его потомки также становятся частью атомарного окна. Если окно не указано, новое окно становится соседним для выбранного окна. Параметр window-atom существующего окна устанавливается в main при условии, что это окно живо и его параметр window-atom ещё не был установлен.

side

Значение такого элемента обозначает сторону существующего окна, с которой должно быть расположено новое окно. Допустимые значения: below, right, above и left. По умолчанию — below. Параметр window-atom нового окна устанавливается в это значение.

Возвращаемое значение — новое окно, nil, если создание этого окна не удалось.

Обратите внимание, что значение параметра window-atom не имеет значения, пока оно не равно nil. Значения, назначаемые display-buffer-in-atom-window, позволяют просто легко получить исходное и новое окно после применения этой функции. Также обратите внимание, что window-atom — единственный параметр окна, назначаемый display-buffer-in-atom-window. Дополнительные параметры должны быть явно установлены приложением через запись window-parameters в alist.

Атомарные окна автоматически перестают существовать, когда одна из их составных частей удаляется. Чтобы разрушить атомарное окно вручную, сбросьте параметр window-atom его составных частей — корня атомарного окна и всех его потомков.

Следующий фрагмент кода при применении к фрейму с одним окном сначала разделяет выбранное окно и делает выбранное и новое окно составными частями атомарного окна с их родителем в качестве корня. Затем он отображает буфер *Messages* в новом окне в нижней части фрейма и делает это новое окно частью только что созданного атомарного окна.

(let ((window (split-window-right)))
  (window-make-atom (window-parent window))
  (display-buffer-in-atom-window
   (get-buffer-create "*Messages*")
   `((window . ,(window-parent window)) (window-height . 5))))

В этот момент нажатие C-x 2 в любом окне этого фрейма создаёт новое окно в нижней части фрейма. Нажатие C-x 3 вместо этого поместит новое окно справа от фрейма. В любом случае, нажатие теперь C-x 1 в любом окне атомарного окна удалит только новое окно. Нажатие C-x 0 в любом окне атомарного окна заставит это новое окно заполнить фрейм.