31.3 Экскурсии

Часто бывает полезно временно перемещать точку в локальной части программы. Это называется экскурсией (excursion) и выполняется с помощью специальной формы save-excursion. Эта конструкция запоминает исходный идентификатор текущего буфера и значение точки в нём, а затем восстанавливает их после завершения экскурсии. Это стандартный способ перемещения точки в одной части программы без влияния на остальную часть программы; она используется тысячи раз в исходных текстах Lisp в Emacs.

Если вам нужно только сохранить и восстановить идентификатор текущего буфера, используйте save-current-buffer или with-current-buffer (см. Текущий буфер). Если вам нужно сохранить или восстановить конфигурации окон, обратитесь к формам, описанным в Конфигурации окон и в Конфигурации фреймов.

Специальная форма: save-excursion body…

Эта специальная форма сохраняет идентификатор текущего буфера и значение точки в нём, вычисляет body и, наконец, восстанавливает буфер и сохранённое значение точки. Оба сохранённых значения восстанавливаются даже в случае аномального выхода через throw или ошибку (см. Нелокальные выходы).

Значение, возвращаемое save-excursion, является результатом последней формы в body или nil, если формы тела не заданы.

Поскольку save-excursion сохраняет точку только для буфера, который был текущим на момент начала экскурсии, любые изменения точки в других буферах во время экскурсии останутся в силе после её завершения. Это часто приводит к непреднамеренным последствиям, поэтому байт-компилятор выдаёт предупреждение, если вы вызываете set-buffer во время экскурсии:

Предупреждение: используйте ‘with-current-buffer’ вместо
         save-excursion+set-buffer

Чтобы избежать таких проблем, следует вызывать save-excursion только после установки нужного текущего буфера, как в следующем примере:

(defun append-string-to-buffer (string buffer)
  "Добавить STRING в конец BUFFER."
  (with-current-buffer buffer
    (save-excursion
      (goto-char (point-max))
      (insert string))))

Аналогично, save-excursion не восстанавливает соответствия окон и буферов, изменённые такими функциями, как switch-to-buffer.

Предупреждение: Обычная вставка текста рядом с сохранённым значением точки перемещает сохранённое значение так же, как перемещаются все маркеры. Точнее, сохранённое значение является маркером с типом вставки nil. См. Типы вставки маркеров. Следовательно, при восстановлении сохранённого значения точки оно обычно оказывается перед вставленным текстом.

Макрос: save-mark-and-excursion body…

Этот макрос подобен save-excursion, но также сохраняет и восстанавливает положение метки и mark-active. Этот макрос делает то, что save-excursion делал до Emacs 25.1.