【问题标题】: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 并对其进行调整以调用传入的函数,从而制作您自己的版本。