Большинство буферов имеют список отмены, который записывает все изменения,
внесённые в текст буфера, чтобы их можно было отменить. (Буферы, у которых
его нет, обычно являются специализированными буферами, для которых Emacs
предполагает, что отмена не полезна. В частности, любой буфер, имя которого
начинается с пробела, по умолчанию имеет отключённую запись отмены;
см. Имена буферов.) Все примитивы, изменяющие
текст в буфере, автоматически добавляют элементы в начало списка отмен,
который находится в переменной buffer-undo-list.
Значение этой локальной переменной буфера является списком отмены текущего
буфера. Значение t отключает запись информации об отмене.
Вот виды элементов, которые может содержать список отмены:
позицияЭлемент такого вида записывает предыдущее значение точки; отмена этого элемента перемещает точку в позицию. Обычное движение курсора не создаёт записей об отмене, но операции удаления используют эти записи, чтобы запомнить, где находилась точка перед командой.
(beg . end)Элемент такого вида указывает, как удалить текст, который был вставлен. При вставке текст занимал диапазон beg–end в буфере.
(текст . позиция)Элемент такого вида указывает, как повторно вставить удалённый текст.
Сам удалённый текст является строкой текст. Место для его
повторной вставки — (abs позиция). Если позиция
положительна, точка находилась в начале удалённого текста, в противном случае —
в конце. Ноль или более элементов (маркер . смещение)
следуют непосредственно за этим элементом.
(t . флаг-времени)Элемент такого вида указывает, что неизменённый буфер стал изменённым.
флаг-времени, являющийся нецелочисленной временной меткой Lisp,
представляет время изменения посещённого файла на момент его последнего
посещения или сохранения, используя тот же формат, что и
current-time; см. Время суток.
флаг-времени равный 0 означает, что буфер не соответствует никакому файлу;
−1 означает, что посещённый файл ранее не существовал.
primitive-undo использует эти
значения, чтобы определить, следует ли снова пометить буфер как неизменённый;
он делает это, только если состояние файла соответствует флагу-времени.
(nil свойство значение beg . end)Элемент такого вида записывает изменение текстового свойства. Вот как можно отменить это изменение:
(put-text-property beg end свойство значение)
(маркер . смещение)Элемент такого вида записывает факт перемещения маркера маркер из-за удаления окружающего текста, и что он переместился на смещение позиций символов. Если положение маркера согласуется с элементом (текст . позиция), предшествующим ему в списке отмены, то отмена этого элемента перемещает маркер на − смещение символов.
(apply имя-функции . аргументы)Это расширяемый элемент отмены, который отменяется вызовом имя-функции с аргументами аргументы.
(apply дельта beg end имя-функции . аргументы)Это расширяемый элемент отмены, который записывает изменение, ограниченное диапазоном beg–end, которое увеличило размер буфера на дельта символов. Он отменяется вызовом имя-функции с аргументами аргументы.
Элемент такого вида позволяет отмене, ограниченной областью, определять, относится ли этот элемент к данной области.
nilЭтот элемент является границей. Элементы между двумя границами называются группой изменений; обычно каждая группа изменений соответствует одной команде клавиатуры, и команды отмены обычно отменяют целую группу как единое целое.
Эта функция помещает элемент-границу в список отмены. Команда
отмены останавливается на такой границе, и последующие команды отмены
отменяют действия до всё более ранних границ. Эта функция возвращает nil.
Явный вызов этой функции полезен для разделения эффектов
команды на более чем одну единицу. Например, query-replace
вызывает undo-boundary после каждой замены, чтобы пользователь мог
отменять отдельные замены по одной.
Однако в большинстве случаев эта функция вызывается автоматически в подходящее время.
Цикл команд редактора автоматически вызывает undo-boundary непосредственно
перед выполнением каждой последовательности клавиш, так что обычно каждая отмена
отменяет эффекты одной команды. Некоторые исключительные команды являются
объединяющимися: эти команды обычно вызывают небольшие изменения в
буферах, поэтому для них граница вставляется только каждую 20-ю команду,
что позволяет отменять изменения как группу. По умолчанию команды
self-insert-command, которая создаёт самостоятельно вставляемые входные
символы (см. Команды вставки пользовательского уровня), и delete-char,
которая удаляет символы (см. Удаление текста), являются объединяющимися.
Если команда затрагивает содержимое нескольких буферов, что может произойти,
например, когда функция из post-command-hook влияет на
буфер, отличный от current-buffer, то undo-boundary
будет вызвана в каждом из затронутых буферов.
Эту функцию можно вызывать перед объединяющейся командой. Она
удаляет предыдущую undo-boundary, если была выполнена серия таких вызовов.
Максимальное количество изменений, которые могут быть объединены, управляется
переменной amalgamating-undo-limit. Если эта переменная равна 1,
изменения не объединяются.
Программа на Lisp может объединить серию изменений в одну группу изменений,
вызвав undo-amalgamate-change-group (см. Атомарные группы изменений). Обратите внимание, что amalgamating-undo-limit не влияет на
группы, создаваемые этой функцией.
Некоторые буферы, например буферы процессов, могут изменяться даже когда
никакие команды не выполняются. В таких случаях undo-boundary
обычно вызывается периодически таймером из этой переменной. Установка
этой переменной в не-nil значение предотвращает такое поведение.
Эта переменная обычно равна nil, но команды отмены связывают её с
t. Это сделано для того, чтобы различные виды перехватчиков изменений
могли определить, что они вызываются в целях отмены.
Это основная функция для отмены элементов списка отмены. Она отменяет первые count элементов list, возвращая оставшуюся часть list.
primitive-undo добавляет элементы в список отмены буфера, когда
он изменяет буфер. Команды отмены избегают путаницы, сохраняя значение
списка отмены в начале последовательности операций отмены. Затем
операции отмены используют и обновляют сохранённое значение. Новые элементы,
добавленные отменой, не являются частью этого сохранённого значения, поэтому
они не мешают продолжению отмены.
Эта функция не связывает undo-in-progress.
Этот макрос удаляет все границы отмены, вставленные во время выполнения body, чтобы его можно было отменить как один шаг.
Некоторые команды оставляют активную область после выполнения таким образом,
что это мешает выборочной отмене этой команды. Чтобы undo
игнорировал активную область при вызове сразу после такой команды,
установите свойство undo-inhibit-region символа функции команды
в не-nil значение. См. Стандартные свойства символов.