【问题标题】:Is there a apply-function-to-region-lines in emacs?emacs 中是否有 apply-function-to-region-lines ?
【发布时间】:2011-09-25 20:23:08
【问题描述】:

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

非常感谢,

D

【问题讨论】:

    标签: function emacs macros elisp


    【解决方案1】:

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

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

    如果你使用kmacro-name-last-macro(绑定到CxCkn),那么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)))
    

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

        下面的函数应该做你想做的事:

        (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 行和第 3 行的区域,输入“Mx apply-function-to-region-lines”,并在提示时输入“test”作为函数名称,你将在缓冲区中得到以下结果:

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

        【讨论】:

        • 为什么要缩小每一行?
        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

          您始终可以将源代码复制到 apply-macro-to-region-lines 并对其进行调整以调用传入的函数,从而制作您自己的版本。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-04-01
            • 2010-12-05
            • 1970-01-01
            • 1970-01-01
            • 2018-03-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多