Spec-Zone.ru › Elisp

Воскрешение окон

После удаления окна (см. Удаление окон) его больше нельзя использовать в функциях, которым требуется действительное окно в качестве аргумента, даже если на это окно всё ещё ссылается какая-либо переменная Lisp. Когда последняя ссылка на окно перестаёт существовать, объект Lisp, представляющий окно, в конечном итоге будет повторно использован сборщиком мусора (см. Сборка мусора).

Есть два способа воскресить удалённое окно, объект которого ещё не был повторно использован сборщиком: первый — сохранить ссылку на это окно в сохранённой конфигурации окон (см. Конфигурации окон), а затем вызвать set-window-configuration, передав эту конфигурацию в качестве аргумента. Второй способ — сохранить ссылку на это окно в переменной или связать её через let, а затем использовать эту ссылку в качестве аргумента refer в split-window (см. Разделение окон).

Основное различие между этими способами состоит в том, что set-window-configuration восстанавливает расположение окон во фрейме таким, каким оно было до удаления окна. Подход с split-window, напротив, позволяет произвольно изменять расположение.

Рассмотрим следующий пример, в котором изначально фрейм содержит одно окно с буфером *scratch*:

(let* ((old (selected-window))
       (new (split-window old nil 'right))
       overlay)
  (with-current-buffer (get-buffer-create "*Messages*")
    (set-window-buffer new (current-buffer))
    (setq overlay (make-overlay (point-min) (point-max)))
    (overlay-put overlay 'face 'highlight)
    (overlay-put overlay 'window new)
    (message "new %s parent %s" new (window-parent new))
    (sit-for 3))
  (delete-window new)
  (setq new (split-window old nil 'left))
  (set-window-buffer new (get-buffer-create "*Messages*"))
  (format "new %s parent %s" new (window-parent new)))

При выполнении этого кода в *scratch* окно с буфером *scratch* сначала разделится, чтобы отобразить *Messages* в новом окне справа. Кроме того, будет создан оверлей со свойством окна для подсветки текста *Messages* в новом окне и выведено сообщение с указанием нового окна и его родителя в дереве окон. Затем новое окно удаляется и воскрешается слева от окна *scratch*; при этом снова выводится сообщение с указанием нового окна и его родителя в дереве окон.

Обратите внимание, что после перемещения окна *Messages* влево изменились и новое окно, и его родитель. Подсветка также исчезает, поскольку все свойства, заданные для нового окна справа, теряются, когда новое окно создаётся заново слева.

В следующем примере вместо этого используется аргумент refer функции split-window.

(let* ((old (selected-window))
       (new (split-window old nil 'right))
       overlay)
  (with-current-buffer (get-buffer-create "*Messages*")
    (set-window-buffer new (current-buffer))
    (setq overlay (make-overlay (point-min) (point-max)))
    (overlay-put overlay 'face 'highlight)
    (overlay-put overlay 'window new)
    (message "new %s parent %s" new (window-parent new))
    (sit-for 3))
  (delete-window new)
  (split-window old nil 'left nil new)
  (format "new %s parent %s" new (window-parent new)))

Обратите внимание, что все свойства воскрешённого окна, например его оформление и параметры, а также любые оверлеи со свойством окна, сохраняются так, словно это окно никогда не удалялось. Изменились только его положение в дереве окон и, как следствие, значения, возвращаемые функцией window-left-child для родительского окна, а также значения, возвращаемые функциями window-prev-sibling и window-next-sibling для окна и его соседнего окна.

В следующем примере и новое окно справа, и его родитель передаются через аргумент refer функции split-window.

(let* ((old (selected-window))
       (new (split-window old nil 'right))
       (parent (window-parent new))
       overlay)
  (with-current-buffer (get-buffer-create "*Messages*")
    (set-window-buffer new (current-buffer))
    (setq overlay (make-overlay (point-min) (point-max)))
    (overlay-put overlay 'face 'highlight)
    (overlay-put overlay 'window new)
    (message "new %s parent %s" new (window-parent new))
    (sit-for 3))
  (delete-window new)
  (split-window old nil 'left nil (cons new parent))
  (format "new %s parent %s" new (window-parent new)))

Обратите внимание, что родительское окно было воскрешено вместе с новым окном.

Воскрешение удалённых окон полезно для сохранения их идентичности при выполнении действий, в которых она должна сохраняться, например при перемещении окон во фрейме или их временном скрытии. Все свойства такого окна, например его оформление, ранее отображавшийся в нём буфер, начальная и текущая позиции этого буфера в окне, состояние закрепления окна или тип его курсора, остаются нетронутыми, и создавать их заново не требуется. Для внутренних окон сохраняется значение ограничения на объединение окон, поэтому окно можно объединить повторно (см. Повторное объединение окон), как и раньше.

Copyright © 1990-1996, 1998-2026 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Resurrecting-Windows.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API