Как отменить call-last-kbd-macro в emacs - PullRequest
7 голосов
/ 27 октября 2010

В emacs я иногда по ошибке вызываю call-last-kbd-macro.При отмене я бы ожидал, что отмена полностью уничтожит эффект макроса клавиатуры, но этого не происходит.Вместо этого я вынужден отменить каждый шаг макроса по одному.Как я могу заставить emacs вернуться в состояние буфера до выполнения макроса?

Ответы [ 2 ]

3 голосов
/ 28 октября 2010

Боюсь, что вы не можете сделать это только с помощью встроенного механизма 'undo.Система макросов в Emacs на самом деле воспроизводит вещи, как если бы пользователь фактически вводил нажатия клавиш (или события мыши), и поэтому история отмен (buffer-undo-list) обновляется как обычно.

Вот предложение о том, как расширить текущий механизм undo, чтобы сделать то, что вы хотите.

  1. extension 'undo, чтобы понять новую запись в списке отмены, a macro-begin маркер и элемент macro-end

  2. советовать / изменять воспроизведение макроса для вставки маркеров в начале / конце воспроизведения макроса

  3. код undo обрабатывает все события отмены между двумя маркерами как единое целое и отменяет их все (и добавляет соответствующие маркеры в конец истории отмены, поэтому, когда вы redo вещи, они по-прежнему рассматриваются какодин блок)

Предостережения:

  • Это будет работать только для макросов, которые работают в одном буфере, если ваши буферы с переключением макросов (или имели побочные эффекты вдругие буферы), эти изменения будутне следует рассматривать как блок.
  • Если ваш макрос заканчивался в другом буфере, чем он начал, то вам нужно было бы справиться с этим чисто - вам не нужны «несбалансированные» маркеры macro-begin и macro-end в списке отмены.

Излишне говорить, что это сложное начинание.Я желаю тебе удачи.

1 голос
/ 11 января 2019

Это можно сделать довольно легко, переопределив undo-boundary, например, с помощью пакета noflet.

С учетом определения макроса (генерируемого insert-kbd-macro) следующим образом:

(fset 'my-macro
   [... keys ...])

или:

(fset 'my-macro
   (lambda (&optional arg) "Keyboard macro." (interactive "p") (kmacro-exec-ring-item (quote ([...keys...] 0 "%d")) arg)))

Отредактируйте его так:

(require 'noflet)

(fset 'my-macro
      (lambda (&optional arg) "Keyboard macro." (interactive "p")
        (undo-boundary)
        (noflet ((undo-boundary ()))
          (kmacro-exec-ring-item (quote ([...keys...] 0 "%d")) arg))
        (undo-boundary)))

Если вы не хотите редактировать все определения макросов, вы можете альтернативно добавить оболочку, которая вызывает макросприводится в качестве аргумента при создании / подавлении отмены границ, как указано выше.

...