Философия отображения буфера
В самом простом виде фрейм вмещает всегда только одно окно, которое может быть использовано для отображения буфера. Вследствие этого, всегда последним вызов display-buffer успешно разместит свой буфер там.
Поскольку работа с таким фреймом не очень практична, Emacs по умолчанию допускает более сложные макеты фреймов, контролируемые значениями размера фрейма и параметрами split-height-threshold и split-width-threshold. Отображение буфера, ещё не показанного в фрейме, затем либо разделяет единственное окно в этом фрейме, либо (повторно) использует одно из двух окон.
Поведение по умолчанию отбрасывается, как только пользователь настраивает один из этих порогов или вручную изменяет макет фрейма. Поведение по умолчанию также отбрасывается при вызове display-buffer с аргументом действие, отличным от nil, или если пользователь настраивает один из параметров, упомянутых в предыдущих подразделах. Овладение display-buffer вскоре может стать разочаровывающим опытом из-за множества применимых действий отображения и результирующих макетов фреймов.
Однако отказ от использования функций отображения буфера и обращение к метафоре разделения и удаления окон тоже не является хорошей идеей. Функции отображения буфера предоставляют программам и пользователям Lisp фреймворк для примирения их различных потребностей; нет сравнимого фреймворка для разделения и удаления окон. Функции отображения буферов также позволяют хотя бы частично восстановить макет фрейма при удалении буфера из него позже (см. Закрытие окон).
Ниже мы приведем ряд рекомендаций, чтобы исправить разочарование, упомянутое выше, и тем самым избежать буквального потери буферов между окнами фрейма.
- Пишите действия отображения без стресса
-
Написание действий отображения может быть проблематичным, потому что необходимо объединить функции действий и списки действий в один большой список. (Исторические причины помешали нам иметь
display-bufferподдержку отдельных аргументов для этих действий.) Это может помочь запомнить некоторые базовые формы, перечисленные ниже:'(nil (inhibit-same-window . t))
указывают только на запись в список действий, но не на функцию действия. Единственная цель – запретить функции
display-buffer-same-window, указанной где-либо ещё, отображать буфер в том же окне, см. также последний пример предыдущего подраздела.'(display-buffer-below-selected)
с другой стороны, указывает одну функцию действия и пустой список действий. Для объединения эффектов двух вышеуказанных спецификаций следует написать форму
'(display-buffer-below-selected (inhibit-same-window . t))
чтобы добавить ещё одну функцию действия, следует написать
'((display-buffer-below-selected display-buffer-at-bottom) (inhibit-same-window . t))
и чтобы добавить ещё одну запись в список, следует написать
'((display-buffer-below-selected display-buffer-at-bottom) (inhibit-same-window . t) (window-height . fit-window-to-buffer))
Последняя форма может использоваться как аргумент действие функции
display-bufferследующим образом:(display-buffer (get-buffer-create "*foo*") '((display-buffer-below-selected display-buffer-at-bottom) (inhibit-same-window . t) (window-height . fit-window-to-buffer)))
При настройке
display-buffer-alistона использовалась бы следующим образом:(customize-set-variable 'display-buffer-alist '(("\\*foo\\*" (display-buffer-below-selected display-buffer-at-bottom) (inhibit-same-window . t) (window-height . fit-window-to-buffer))))Для добавления настройки для второго буфера следует написать:
(customize-set-variable 'display-buffer-alist '(("\\*foo\\*" (display-buffer-below-selected display-buffer-at-bottom) (inhibit-same-window . t) (window-height . fit-window-to-buffer)) ("\\*bar\\*" (display-buffer-reuse-window display-buffer-pop-up-frame) (reusable-frames . visible)))) - Обращайтесь друг к другу с уважением
-
display-buffer-alistиdisplay-buffer-base-action— это параметры пользователя; программы Lisp никогда не должны устанавливать или переопределять их.display-buffer-overriding-action, с другой стороны, зарезервирован для приложений, которые редко используют этот параметр, и если используют, то с большой осторожностью.Старые реализации
display-bufferчасто заставляли пользователей и приложения бороться за настройки параметров пользователей, таких какpop-up-framesиpop-up-windows(см. Выбор параметров окна). Это была одна из основных причин переработкиdisplay-buffer— для предоставления ясной структуры, определяющей, что пользователи и приложения должны иметь право делать.Программы Lisp должны быть готовы к тому, что пользовательские настройки могут привести к отображению буферов неожиданным образом. Они никогда не должны предполагать в своём последующем поведении, что буфер был показан ровно так, как они запросили в аргументе действие функции
display-buffer.Пользователи не должны накладывать слишком много и слишком строгих ограничений на то, как отображаются произвольные буферы. В противном случае они рискуют потерять характеристики отображения буфера для определённой цели. Предположим, что программа Lisp написана для сравнения различных версий буфера в двух окнах бок о бок. Если настройка
display-buffer-alistпредписывает, что любой такой буфер всегда должен отображаться в или ниже выбранного окна, программе будет сложно настроить желаемую конфигурацию окна с помощьюdisplay-buffer.Чтобы указать предпочтение отображения произвольного буфера, пользователи должны настроить
display-buffer-base-action. Пример того, как пользователи, предпочитающие работать с несколькими фреймами, сделают это, был приведен в предыдущем подразделе.display-buffer-alistдолжен быть зарезервирован для отображения конкретных буферов определённым способом. - Рассмотрите возможность повторного использования окна, которое уже отображает буфер
-
В общем случае, для пользователей и программистов Lisp всегда полезно быть готовыми к тому, что окно уже отображает нужный буфер, и повторно использовать это окно. В предыдущем подразделе мы показали, что, не сделав этого должным образом, может привести к тому, что
display-bufferбудет постоянно открывать новый фрейм, хотя уже существовал фрейм, отображающий этот буфер. В немногих случаях может быть нежелательно повторно использовать окно, например, когда в этом окне должна отображаться другая часть буфера.Следовательно,
display-buffer-reuse-window— это одна функция действия, которую следует использовать как можно чаще, как в аргументах действие, так и в настройках. Записьinhibit-same-windowв аргументе действие обычно обрабатывает наиболее распространённый случай, когда следует избегать повторного использования окна, отображающего буфер, — тот, где окно в вопросе выбрано. - Привлечь внимание к выбранному окну
-
Это очевидно для людей, работающих с несколькими фреймами: фрейм, отображающий буфер, автоматически поднимется и получит фокус, если запись
inhibit-switch-frameне запретит это. Для пользователей с одним фреймом эта задача может быть значительно сложнее. В частности,display-buffer-pop-up-windowиdisplay-buffer-use-some-windowмогут стать раздражительными в этом отношении. Они делят или используют, казалось бы, произвольное (часто самое большое или наименее используемое) окно, отвлекая внимание пользователя.Поэтому некоторые программы Lisp пытаются выбрать окно в нижней части фрейма, например, чтобы отобразить буфер вблизи окна минибуфера, где ожидается, что пользователь ответит на вопрос, связанный с новым окном. Для действий, не связанных с вводом,
display-buffer-below-selectedможет быть предпочтительнее, потому что выбранное окно обычно уже привлекает внимание пользователя. - Обработка последующих вызовов
display-buffer -
display-bufferне очень подходит для отображения нескольких буферов последовательно и обеспечения упорядоченного отображения всех этих буферов в результирующей конфигурации окна. Стандартные функции действияdisplay-buffer-pop-up-windowиdisplay-buffer-use-some-windowтакже не очень подходят для этой цели из-за своей несколько хаотичной природы в более сложных конфигурациях.Для создания конфигурации окна, отображающей несколько буферов (или разных представлений одного и того же буфера) в одном и том же цикле отображения, программистам Lisp неизбежно придётся писать свои собственные функции действий. Несколько приёмов, перечисленных ниже, могут помочь в этом.
- Преобразование окон в атомарные (см. Атомарные окна) предотвращает разрыв существующей композиции окна при появлении нового окна. Новое окно вместо этого появится за пределами композиции.
- Временное выделение окон для их буферов (см. Выделенные окна) предотвращает использование окна для отображения другого буфера. Вместо этого будет использоваться не выделенное окно.
- Вызов
window-preserve-size(см. Сохранение размеров окна) попытается сохранить размер окна-аргумента неизменным при появлении нового окна. Однако нужно убедиться, что другое окно в той же комбинации может быть уменьшено вместо этого. - Побочные окна (см. Побочные окна) могут использоваться для отображения определенных буферов всегда в окне в том же положении фрейма. Это позволяет группировать буферы, которые не конкурируют за отображение в одном и том же фрейме, и отображать любой такой буфер в одном и том же окне, не нарушая отображения других буферов.
- Вложенные фреймы (см. Вложенные фреймы) могут быть использованы для отображения буфера в области экрана выбранного фрейма без нарушения конфигурации окна этого фрейма и без накладных расходов, связанных с полноценными фреймами, как это происходит при использовании
display-buffer-pop-up-frame.
Copyright © 1990-1996, 1998-2022 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/The-Zen-of-Buffer-Display.html