如何在Emacs中将kbd-macro转换为实际命令?

时间:2014-03-06 13:56:21

标签: emacs macros

似乎kbd-macro只记录我推送的密钥。但是我想记录真实的命令(与我按下的键绑在一起)并将它们保存为函数。

所以我的问题就像是跟随。 如何记录我用作可执行格式的命令? 如何将键序列转换为命令序列? 如何将my-kbd-macro转换为命令序列函数?

示例:

F3 M-x kmacro-start-macro

C-f

F4 M-x kmacro-end-or-call-macro

M-x name-last-kbd-macro my-kbd-macro

M-x insert-kbd-macro my-kbd-macro

输出:

(fset 'my-kbd-macro
   "\C-f")

我想要的输出如下:

(defun my-kbd-macro ()
  (interactive)
  (forward-char)
)

感谢。

2 个答案:

答案 0 :(得分:1)

这是您想要的简单实现。 它仅适用于不需要输入的简单命令,如forward-char。 以完全自动化的方式做任何事情似乎很难/不可行。这就是为什么这个功能 我想,它已经不存在了。

我已将这些功能添加到 my macro package that allows multiple anonymous macros 您可以从github或MELPA中获取centimacro

要使用它,只需执行 F3 ... F4 即可 例如, M-x last-macro-to-defun *scratch*

(defun macro->defun (str)
  "Convert macro representation STR to an Elisp string."
  (let ((i 0)
        (j 1)
        (n (length str))
        forms s f)
    (while (< i n)
      (setq s (substring str i j))
      (setq f (key-binding s))
      (if (keymapp f)
          (incf j)
        (push (list f) forms)
        (setq i j)
        (setq j (1+ i))))
    (with-temp-buffer
      (emacs-lisp-mode)
      (insert
       "(defun foo ()\n  (interactive)")
      (mapc (lambda (f)
              (newline-and-indent)
              (insert (prin1-to-string f)))
            (nreverse forms))
      (insert ")")
      (buffer-string))))

(defun last-macro-to-defun ()
  "Insert last macro as defun at point."
  (interactive)
  (insert (macro->defun last-kbd-macro)))

答案 1 :(得分:1)

请记住,在编写函数时,通常有更好的方法来做事,而不是完全模仿交互式绑定,所以虽然不是必要,但如果你有一些重构可能会有所帮助从宏运行时使用的命令开始。

无论如何,我可以想出一些有用的工具来协助手动解决这个问题:

首先,如果您编辑一个键盘宏,宏编辑器会使用它所绑定的函数对每个键进行注释(nb用于调用编辑器的缓冲区! - 如果您正在切换在宏执行时缓冲,我建议检查每个缓冲区的编辑器。)

显然,您可以通过其他方式获取相同的信息,但宏编辑器会为您提供整个列表,这可能很方便。

另一个助手是repeat-complex-command绑定到 Cx M - :,它会从某些类型的交互式函数调用中为您提供生成的elisp表单(“a复杂命令是使用迷你缓冲区的命令。我最喜欢的例子是align-regexp,因为它是用户的交互式参数被进一步操纵的情况,这不一定是显而易见的。 e.g:

Mx align-regexp RET = RET Cx M- :可能会告诉你:

(align-regexp 1 191 "\\(\\s-*\\)=" 1 1 nil)