emacs中是否存在apply-function-to-region-lines?

时间:2011-06-30 09:45:30

标签: function emacs macros elisp

我的很多工作都涉及搜索和删除不必要的代码行。所以我创建一个宏,然后选择所有行(C-x h),然后运行命令(apply-macro-to-region-lines)。我设法保存该命令并将其放在我的.emacs文件中;我叫它cut_it_now。但是现在我的函数不再是宏了,所以我再也不能使用(apply-macro-to-region-lines)函数了。 你知道在某个地方是否实现了(apply-function-to-region-lines)吗?

非常感谢,

d

5 个答案:

答案 0 :(得分:5)

请注意,您仍然可以将apply-macro-to-region-lines与代码生成的宏一起使用,提供宏定义为向量或字符串。使用自定义apply-named-macro-to-region-lines [2],您可以选择要以交互方式使用的宏。

Emacs有两种从键盘宏生成代码的方法,具体取决于命名它的方法。

如果使用kmacro-name-last-macro(绑定到 Cx Ck n ),则Emacs会生成函数来自宏,这对于这个特定目的并不直接有用[1]。

如果使用name-last-kbd-macro命名宏,则会将其生成为矢量或字符串。

在任何一种情况下,您都可以使用insert-kbd-macro来获取代码。

实际上,矢量/字符串格式是默认格式,因此您可以绕过命名步骤并立即询问代码(在名称提示符下键入 RET 以指示最近定义的宏) ,然后手动编辑插入代码的默认名称。

[1]:矢量形式似乎只是嵌入在函数定义中,因此您应该能够从代码中提取它以手动重新定义矢量格式的宏函数。

[2]:当我最初写这篇回复时,我忘了这是一个自定义功能。对不起。

(defun apply-named-macro-to-region-lines (top bottom)
  "Apply named keyboard macro to all lines in the region."
  (interactive "r")
  (let ((macro (intern
                (completing-read "kbd macro (name): "
                                 obarray
                                 (lambda (elt)
                                   (and (fboundp elt)
                                        (or (stringp (symbol-function elt))
                                            (vectorp (symbol-function elt))
                                            (get elt 'kmacro))))
                                 t))))
    (apply-macro-to-region-lines top bottom macro)))

答案 1 :(得分:4)

一个简单的解决方案是定义一个调用你的函数的宏,然后使用好的'apply-macro-to-region-lines

除此之外,我认为你可以在几行elisp中写一个完全符合你要求的循环。如果您想要花哨,您甚至可以提示用户输入该功能的名称。我认为这对elisp来说是一个很好的练习,如果您想自己尝试一下,我可以帮您指点。

答案 2 :(得分:4)

以下功能应该符合您的要求:

(defun apply-function-to-region-lines (fn)
  (interactive "aFunction to apply to lines in region: ")
  (save-excursion
    (goto-char (region-end))
    (let ((end-marker (copy-marker (point-marker)))
          next-line-marker)
      (goto-char (region-beginning))
      (if (not (bolp))
          (forward-line 1))
      (setq next-line-marker (point-marker))
      (while (< next-line-marker end-marker)
        (let ((start nil)
              (end nil))
          (goto-char next-line-marker)
          (save-excursion
            (setq start (point))
            (forward-line 1)
            (set-marker next-line-marker (point))
            (setq end (point)))
          (save-excursion
            (let ((mark-active nil))
              (narrow-to-region start end)
              (funcall fn)
              (widen)))))
      (set-marker end-marker nil)
      (set-marker next-line-marker nil))))

因此,如果您要对缓冲区中的行应用以下函数:

(defun test()
  (insert "> "))

并且,如果您的缓冲区包含以下内容:

Line 1: blah, blah
Line 2: blah, blah
Line 3: blah, blah
Line 4: blah, blah

如果您选择仅包围第2行和第2行的区域3,输入“M-x apply-function-to-region-lines”,并在提示时输入“test”作为函数名称,您将在缓冲区中得到以下结果:

Line 1: blah, blah
> Line 2: blah, blah
> Line 3: blah, blah
Line 4: blah, blah

答案 3 :(得分:3)

我同意@ Lindydancer的回答,并且我还补充说,可能有一种更简单的方法来实现您的目标。例如内置函数delete-matching-lines。 : - )

答案 4 :(得分:-1)

您可以随时将源复制到apply-macro-to-region-lines并调整它以调用传入的函数,从而创建自己的版本。