Текущий буфер
В сеансе Emacs, как правило, имеется множество буферов. В любой момент времени один из них обозначается как текущий буфер — буфер, в котором в основном происходит редактирование. Большинство примитивов для просмотра или изменения текста неявно работают с текущим буфером (см. Текст).
Обычно буфер, отображаемый в выбранном окне (см. Выбор окон), является текущим буфером, но это не всегда так: программа Lisp может временно обозначить любой буфер как текущий для работы с его содержимым без изменения отображаемого на экране. Наиболее базовая функция для обозначения текущего буфера — set-buffer.
- Функция: current-buffer
-
Эта функция возвращает текущий буфер.
(current-buffer) ⇒ #<buffer buffers.texi>
- Функция: set-buffer buffer-or-name
-
Эта функция делает buffer-or-name текущим буфером. buffer-or-name должен быть существующим буфером или именем существующего буфера. Возвращаемое значение — буфер, сделанный текущим.
Эта функция не отображает буфер ни в одном окне, поэтому пользователь не обязательно увидит буфер. Но программы Lisp теперь будут с ним работать.
Когда команда редактирования возвращается к циклу команд редактора Emacs, Emacs автоматически вызывает set-buffer для буфера, отображаемого в выбранном окне (см. Выбор окон). Это сделано для предотвращения путаницы: это гарантирует, что буфер, в котором находится курсор, когда Emacs считывает команду, является буфером, к которому эта команда применяется (см. Цикл команд). Таким образом, вы не должны использовать set-buffer для видимого переключения на другой буфер; для этого используйте функции, описанные в Переключение между буферами.
При написании функции Lisp не полагайтесь на это поведение цикла команд для восстановления текущего буфера после операции. Команды редактирования также могут вызываться как функции Lisp другими программами, а не только из цикла команд; для вызывающей стороны удобно, если подпрограмма не изменяет текущий буфер (если, конечно, это не цель подпрограммы).
Для временной работы с другим буфером поместите set-buffer в форму save-current-buffer. Вот здесь, в качестве примера, упрощенная версия команды append-to-buffer:
(defun append-to-buffer (buffer start end)
"Append the text of the region to BUFFER."
(interactive "BAppend to buffer: \nr")
(let ((oldbuf (current-buffer)))
(save-current-buffer
(set-buffer (get-buffer-create buffer))
(insert-buffer-substring oldbuf start end))))
Здесь мы связываем локальную переменную для записи текущего буфера, а затем save-current-buffer организует его повторное присвоение в качестве текущего позже. Затем set-buffer делает указанный буфер текущим, а insert-buffer-substring копирует строку из исходного буфера в указанный (и теперь текущий) буфер.
В качестве альтернативы, мы можем использовать макрос with-current-buffer:
(defun append-to-buffer (buffer start end)
"Append the text of the region to BUFFER."
(interactive "BAppend to buffer: \nr")
(let ((oldbuf (current-buffer)))
(with-current-buffer (get-buffer-create buffer)
(insert-buffer-substring oldbuf start end))))
В любом случае, если буфер, который был добавлен, отображается в каком-либо окне, при следующем перерисовывании будет видно, как изменился его текст. Если он не отображается ни в одном окне, вы не увидите изменения на экране немедленно. Команда делает буфер временным текущим, но не отображает его.
Если вы создаёте локальные привязки (с помощью let или аргументов функций) для переменной, которая также может иметь буферно-локальные привязки, убедитесь, что один и тот же буфер является текущим в начале и в конце области действия локальной привязки. В противном случае вы можете привязать её в одном буфере и отменить привязку в другом!
Не полагайтесь на использование set-buffer для возврата текущего буфера, потому что это не сработает, если произойдет выход из программы, в то время как неправильный буфер является текущим. Например, в предыдущем примере было бы неправильно сделать следующее:
(let ((oldbuf (current-buffer)))
(set-buffer (get-buffer-create buffer))
(insert-buffer-substring oldbuf start end)
(set-buffer oldbuf))
Использование save-current-buffer или with-current-buffer, как мы сделали, правильно обрабатывает выход из программы, ошибки и throw, а также обычное вычисление.
- Специальная форма: save-current-buffer body…
-
Специальная форма
save-current-bufferсохраняет идентификатор текущего буфера, вычисляет формы body, а затем восстанавливает этот буфер в качестве текущего. Возвращаемое значение — значение последней формы в body. Текущий буфер восстанавливается даже в случае аварийного выхода черезthrowили ошибки (см. Нелокальные выходы).Если буфер, который раньше был текущим, был убит к моменту выхода из
save-current-buffer, то, конечно, он не становится текущим снова. Вместо этого текущим остаётся тот буфер, который был текущим непосредственно перед выходом.
- Макрос: with-current-buffer buffer-or-name body…
-
Макрос
with-current-bufferсохраняет идентификатор текущего буфера, делает buffer-or-name текущим, вычисляет формы body и, наконец, восстанавливает текущий буфер. buffer-or-name должен указать существующий буфер или имя существующего буфера.Возвращаемое значение — значение последней формы в body. Текущий буфер восстанавливается даже в случае аварийного выхода через
throwили ошибки (см. Нелокальные выходы).
- Макрос: with-temp-buffer body…
-
Макрос
with-temp-bufferвычисляет формы body с временным буфером в качестве текущего буфера. Он сохраняет идентификатор текущего буфера, создаёт временный буфер и делает его текущим, вычисляет формы body и, наконец, восстанавливает предыдущий текущий буфер, уничтожая временный буфер.По умолчанию информация об отмене (см. Отмена) не записывается в буфер, созданный этим макросом (но body может это разрешить, если необходимо). Временный буфер также не выполняет хуки
kill-buffer-hook,kill-buffer-query-functions(см. Уничтожение буферов) иbuffer-list-update-hook(см. Список буферов).Возвращаемое значение — значение последней формы в body. Вы можете вернуть содержимое временного буфера, используя
(buffer-string)в качестве последней формы.Текущий буфер восстанавливается даже в случае аварийного выхода через
throwили ошибки (см. Нелокальные выходы).См. также
with-temp-fileв Запись в файлы.
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/Current-Buffer.html