如何为emacs宏添加动态触摸和/或查询替换?

时间:2012-04-30 17:03:49

标签: emacs lisp elisp

我经常发现自己需要连续多次查询和替换操作,因为例如我想要在一行中更改23到24的所有出现,然后在下一行中更改24到25,依此类推(通常)因为我在一行中写了一个表达式,我在后续行中多次猛拉并需要稍微修改一下...... ...

具有Cx q或常规执行多个查询替换的宏在这样的情况下看起来不够强大......有一些更通用/更灵活的处理变量替换或可变宏变体这样我可以看成?我相信我曾经遇到过网络上的一个例子,其中lisp表达式被引入某些命令以更强大但我无法记住这个或我在哪里读到它..

4 个答案:

答案 0 :(得分:6)

我不确定这完全回答了你的问题,但我发现寄存器是构建强大宏的有用工具。最重要的功能是:

  • C-x r n number-to-register将该点的数字复制到一个寄存器中
  • C-x r + increment-register递增存储在寄存器中的值
  • C-x r i insert-register将寄存器的值插入缓冲区

使用这些功能,您可以解决使用以下方法替换每行上的递增数字的问题:

  • 将第一个号码播种到number-to-register
  • 的注册表中
  • 启动宏定义
  • 选择一行
  • replace-stringinsert-registerincrement-registerinsert-register
  • 移至下一行的开头
  • 结束宏定义

emacs手册中有关于寄存器的更多信息:https://www.gnu.org/software/emacs/manual/html_node/emacs/Registers.html

答案 1 :(得分:3)

除了现有命令的巧妙使用,例如ataylor所示的命令,键盘宏可用于执行几乎任意复杂和动态的行为。

特别需要注意的是, Cu M - :会在当前缓冲区中插入您输入的任何elisp表单的结果 - 当然,这种形式可以是构造为宏的一部分 - 因此,即使特定操作没有命令,也不可能阻止使用宏来实现目标。

(当然,如果elisp不是答案, Cu M - ! Cu M- | 也让您轻松访问合并shell命令输出。)

当然,有些情况下可以使用更有针对性的解决方案,而且宏比其价值更麻烦(在评论中链接的“搜索和替换elisp评估”技术也非常强大,而且往往是理想的解决方案);然而键盘宏也提供了惊人的功率,而且可以轻松地做一些事情,你可能很难做到这一点。

我最喜欢的一个例子是在一个缓冲区中使用“old - > new”映射数据(几乎可以想象的任何格式)并使用它来对另一个缓冲区中的那些值执行搜索和替换。只需简单的移动和编辑按键,您就可以在临时的基础上进行此类操作的速度令人惊叹。

宏编辑器还可以轻松调整宏,如果第一次不正确,无需重新录制所有步骤。

我曾经读过一些有用的建议,这只是为了总是考虑一下,当你遇到一些非常重要的事情时,你是否可以用键盘宏完成任务。您使用它们越多,您就越能意识到可以使用它们的不同方式,很快您就会在工具箱中拥有一个新的不可或缺的工具。

答案 2 :(得分:2)

您询问的具体情况听起来像是使用query-replace-regexp的理想场所。

M-x query-replace-regexp
Regexp: \([0-9]+\)
Replace with: \,(+ 1 (string-to-number \1))

该用法将找到一个或多个数字的所有集合(Emacs正则表达式不支持\d)并用它们的增量替换它们,每次都提示。

关键要点是:

  • 捕获的组是您可以在替换操作中调用的字符串
  • 您可以使用\,
  • 将任意代码拼接到替换操作中
  • 您可以在任何以这种方式拼写的代码中使用捕获的组作为参数

答案 3 :(得分:1)

这是您所述问题的另一种可能的解决方案,使用elisp替换和键盘宏计数器,您可以使用数字前缀参数进行种子处理。

(我不会说这是更好,但它展示了另一种可用选项。)

因此假设23是起始编号,您可以定义以下宏,从:

开始

C-2 C-3 F3

C-SPC       ;; set-mark-command
C-e         ;; move-end-of-line
<<replace-regexp>>  ;; replace-regexp
<f3>        ;; kmacro-start-macro-or-insert-counter
C--         ;; negative-argument
M-@         ;; mark-word
M-w         ;; kill-ring-save
RET         ;; indent-new-comment-line
\           ;; self-insert-command
,(1+        ;; self-insert-command * 4
SPC         ;; self-insert-command
C-y         ;; yank
)           ;; self-insert-command
RET         ;; indent-new-comment-line

F4 停止录制。

(n.b。此宏假定区域中的每一行都包含序列中的值。)

然后突出显示剩余的行并使用 C-x C-k r 来更新该区域中的所有行。

您可以使用 Cx Ck Cc 将宏计数器重新设置为任何所需的值,以在另一个区域重新播放宏。

根据您的数据实际情况,您可以通过完全取消replace-regexp来大大简化,而只需移动到您知道数字的位置,删除现有数字,并插入计数器值它的位置。