29.3 Выбор окон

В каждом фрейме в любой момент времени ровно одно окно Emacs обозначается как выбранное в фрейме. Для выбранного фрейма это окно называется выбранным окном — тем, в котором происходит большая часть редактирования, и в котором отображается курсор для выбранных окон (см. Параметры курсора). Ввод с клавиатуры, добавляющий или удаляющий текст, также обычно направляется в это окно. Буфер выбранного окна обычно также является текущим буфером, за исключением случаев, когда использовалась функция set-buffer (см. Текущий буфер). Что касается невыбранных фреймов, окно, выбранное в фрейме, становится выбранным окном, если фрейм когда-либо выбирается.

Функция: selected-window

Эта функция возвращает выбранное окно (которое всегда является активным окном).

Следующая функция явно выбирает окно и его фрейм.

Функция: select-window window &optional norecord

Эта функция делает window выбранным окном и окном, выбранным в его фрейме, и выбирает этот фрейм. Она также делает буфер window (см. Буферы и окна) текущим и устанавливает значение point этого буфера в window равным значению window-point (см. Окна и точка) в window. window должен быть активным окном. Значение возвращаемое — window.

По умолчанию эта функция также перемещает буфер window в начало списка буферов (см. Список буферов) и делает window последним выбранным окном. Если необязательный аргумент norecord не равен nil, эти дополнительные действия опускаются.

Кроме того, по умолчанию эта функция также сообщает дисплейному движку обновить отображение window, когда его фрейм будет показан повторно в следующий раз. Если norecord не равен nil, такие обновления обычно не выполняются. Однако, если norecord равно специальному символу mark-for-redisplay, дополнительные действия, упомянутые выше, опускаются, но отображение window тем не менее обновляется.

Обратите внимание, что иногда выбора окна недостаточно, чтобы его показать или сделать его фрейм самым верхним на дисплее: возможно, вам также потребуется поднять фрейм или убедиться, что фокус ввода направлен на этот фрейм. См. Фокус ввода.

По историческим причинам Emacs не запускает отдельный хук каждый раз, когда выбирается окно. Приложения и внутренние процедуры часто временно выбирают окно, чтобы выполнить несколько действий над ним. Они делают это либо для упрощения кодирования — поскольку многие функции по умолчанию работают с выбранным окном, когда не указан аргумент window — либо потому что некоторые функции не принимали (и до сих пор не принимают) окно в аргументе и всегда работали(ют) с выбранным окном вместо этого. Запуск хука каждый раз, когда выбирается окно, на короткое время, и еще один раз, когда восстанавливается ранее выбранное окно, не полезен.

Однако, когда его аргумент norecord равен nil, select-window обновляет список буферов и таким образом косвенно выполняет обычный хук buffer-list-update-hook (см. Список буферов). Следовательно, этот хук предоставляет один способ запустить функцию всякий раз, когда выбирается окно более «постоянно».

Поскольку buffer-list-update-hook также вызывается функциями, не связанными с управлением окнами, обычно имеет смысл сохранить значение выбранного окна где-нибудь и сравнить его со значением selected-window при выполнении этого хука. Кроме того, чтобы избежать ложных срабатываний при использовании buffer-list-update-hook, хорошей практикой является то, что каждый вызов select-window, предназначенный для временного выбора окна, передает не-nil аргумент norecord. Если возможно, в таких случаях следует использовать макрос with-selected-window (см. ниже).

Emacs также запускает хук window-selection-change-functions всякий раз, когда процедура повторного отображения обнаруживает, что другое окно было выбрано с момента последнего повторного отображения. См. Хуки для прокрутки и изменений окон, для подробного объяснения. window-state-change-functions (описанный в том же разделе) — еще один аномальный хук, запускаемый после того, как было выбрано другое окно, но также вызываемый другими изменениями окон.

Последовательность вызовов select-window с не-nil аргументом norecord определяет порядок окон по времени их выбора или использования, см. ниже. Например, функцию get-lru-window можно затем использовать для получения наименее недавно выбранного окна (см. Циклический порядок окон).

Функция: frame-selected-window &optional frame

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

Функция: set-frame-selected-window frame window &optional norecord

Эта функция делает window окном, выбранным в фрейме frame. frame должен быть активным фреймом; если он равен nil, по умолчанию используется выбранный фрейм. window должен обозначать активное окно.

Если frame является выбранным фреймом, это делает window выбранным окном.

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

Следующие макросы полезны для временного выбора окна без влияния на порядок недавно выбранных окон или список буферов.

Макрос: save-selected-window forms…

Этот макрос записывает выбранный фрейм, а также выбранное окно каждого фрейма, выполняет forms последовательно, а затем восстанавливает ранее выбранный фрейм и окна. Он также сохраняет и восстанавливает текущий буфер. Он возвращает значение последнего элемента в forms.

Этот макрос не сохраняет и не восстанавливает ничего о размерах, расположении или содержимом окон; поэтому, если forms изменяют их, изменение сохраняется. Если ранее выбранное окно какого-либо фрейма больше не активно на момент выхода из forms, выбранное окно этого фрейма остается без изменений. Если ранее выбранное окно больше не активно, то какое бы окно ни было выбрано в конце forms, оно остается выбранным. Текущий буфер восстанавливается только в том случае, если он все еще активен при выходе из forms.

Этот макрос не изменяет ни порядок недавно выбранных окон, ни список буферов.

Макрос: with-selected-window window forms…

Этот макрос выбирает window, выполняет forms последовательно, а затем восстанавливает ранее выбранное окно и текущий буфер. Порядок недавно выбранных окон и список буферов остаются без изменений, если вы намеренно не измените их внутри forms; например, вызвав select-window с аргументом norecord nil. Таким образом, этот макрос является предпочтительным способом временной работы с window как с выбранным окном без ненужного запуска buffer-list-update-hook.

Обратите внимание, что этот макрос временно помещает код управления окнами в нестабильное состояние. В частности, наиболее часто используемое окно (см. ниже) не обязательно совпадет с выбранным. Следовательно, такие функции, как get-lru-window и get-mru-window, могут вернуть неожиданные результаты при вызове из тела этого макроса.

Макрос: with-selected-frame frame forms…

Этот макрос выполняет forms с frame как выбранный фрейм. Возвращаемое значение — это значение последнего элемента в forms. Этот макрос сохраняет и восстанавливает выбранный фрейм и не изменяет порядок ни недавно выбранных окон, ни буферов в списке буферов.

Функция: window-use-time &optional window

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

Время использования окна — это на самом деле не значение времени, а целое число, которое монотонно увеличивается при каждом вызове select-window с аргументом nil norecord. Окно с наименьшим временем использования обычно называется наименее недавно использованным окном. Окно с наибольшим временем использования называется наиболее недавно использованным (см. Циклический порядок окон) и обычно является выбранным окном, если не использовался with-selected-window.

Функция: window-bump-use-time &optional window

Эта функция помечает window как второе по недавности использованное (после выбранного окна). Она ничего не делает, если window является выбранным окном или если выбранное окно не имеет наибольшего времени использования среди всех окон, что может случиться в области действия with-selected-window.

Иногда несколько окон совместно и взаимодействуя отображают буфер, например, под управлением (emacs)Follow Mode, где окна вместе отображают большую часть буфера, чем могло бы отобразить одно окно. Часто полезно рассматривать такую группу окон как единый объект. Несколько функций, таких как window-group-start (см. Позиции начала и конца окна), позволяют сделать это, предоставляя в качестве аргумента одно из окон в качестве заместителя для всей группы.

Функция: selected-window-group

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

Выбранное окно считается частью группы, когда локальная переменная буфера selected-window-group-function установлена в функцию. В этом случае selected-window-group вызывает ее без аргументов и возвращает ее результат (который должен быть списком окон в группе).