在Emacs中同时编辑多行

85

我相信TextMate有一个模式,如果你开始输入,选中的所有行都会输入相同的内容。Emacs中是否有类似的功能?

我猜矩形可以帮助我,但我不确定怎么做...


你应该尝试这个:https://github.com/magnars/mark-multiple.el 演示视频:http://www.youtube.com/watch?v=r2o9HYi7DOY - whunmr
如果你重新阅读一下帮助笔记,你会发现自从它最初发布以来,已经被multiple-cursors.el所取代。 - phils
是的,@phils,multiple-cursors.el 真的很棒。 - whunmr
参见:https://dev59.com/kV0b5IYBdhLWcg3wA9Ab - dreftymac
10个回答

111

9
这很棒,但对于完全不了解Emacs的人来说并不是非常有用,你能帮我破译一下吗? - cone
3
你应该阅读内置的Emacs教程。它会解释如何阅读象形文字 ;)。在Emacs中打开教程,请按住Ctrl键并同时按下'h',然后按下't'(即"tutorial") 。 - allyourcode
1
我已经将C-x映射到剪切(cua-mode),所以这不是一个好主意。 - mefiX
28
也许你认为将 C-x 键映射为剪切不太好 :) - BartoszKP
注意:此命令将选定的矩形替换为指定的字符串,即选择行的开头才能进行替换。 - Beginner
1
@cone 我可以使用这个方法将多行文本制作成列表,只需使用 C-<SPC> 设置标记,然后使用 C-g。接着我使用 C-x r t,在迷你缓冲区中输入 - (破折号和一个空格),最后按下 <RET> 键。哇!一个列表就被创建了。 - Kent Bull

58

1
这是一个很好的解决方案。非常易于使用。要从点击中添加多个选择(包括我在内的大多数人的标准),请将(global-unset-key (kbd "M-<down-mouse-1>"))(global-set-key (kbd "M-<mouse-1>") 'mc/add-cursor-on-click)添加到您的配置中。 - smonff
在2021年,这是我认为大多数人会期望的解决方案。 - Mike Andrews
它甚至与swiper集成,'C-7'作为默认的键绑定。https://xenodium.com/emacs-swiper-and-multiple-cursors/ - Mike Andrews

23

其中之一的解决方案是使用CUA模式。使用M-x cua-mode激活CUA模式,选择矩形开始:首先按下C-Enter,然后使用标准移动命令移动光标以进行选择,现在随时按下回车键将循环光标通过矩形的角落,使您能够在选择的文本之前或之后添加文本。


谢谢,boskom。我正在使用21.3.1版本,所以这种模式似乎没有安装。我可能不会安装它,因为我发现我喜欢C-x r t。 - allyourcode
1
谢谢!我只是认为CUA模式是为那些不想学习Emacs复制和粘贴绑定的人准备的:P 这太棒了! - rflood89
2
如果您使用cua-selection-mode而不是cua-mode,则不会获得不需要的剪切/复制/粘贴绑定。但是,您将获得一些其他功能,这可能不是您想要的(最明显的是,编辑命令将替换区域)。 - phils

22

对于那些希望在更复杂的情况下进行操作且不想安装新模块的人,请继续阅读。(在Emacs中没有安装MarkMultiple也是可能的,尽管我个人使用和喜欢MarkMultiple。)

最近我不得不将SQL查询结果输出到文件中,并将其格式化为“MYSQL INSERT”查询。下面是Emacs如何简化我的生活:

文件如下:

1   I am a random text
2    I am not
3    G, you've gone mad
4    Click on this link
5   Transfer in progress (we've started the transfer process)
6    But transfer happened yesterday
7    No you are
8    Oh please! This is getting too much!
9    I love Emacs
10    I can't be bothered with    this any more
11    it's time to raise the bar
12    show me    how to expand my territory

我希望让它看起来像这样:

(1,   ,'I am a random text'),
(2,   ,'I am not'),
(3,   ,'G, youve gone mad'),
(4,   ,'Click on this link'),
(5,   ,'Transfer in progress (weve started the transfer process)'),
(6,   ,'But transfer happened yesterday'),
(7,   ,'No you are'),
(8,   ,'Oh please! this is getting too much!'),
(9,   ,'I love Emacs'),
(10,  ,'I cant be bothered with this any more'),
(11,  ,'its time to raise the bar'),
(12,  ,'show me how to expand my territory'),
  1. 将光标置于第一行
  2. 按下 C-x ( 开始录制宏(此时,所有按键都正在被记录,请仔细跟随说明)
  3. 按下 C-a 移动到行的开始处
  4. 输入“(”,然后按下 M-f 向前移动一个单词并输入“,”
  5. C-n 跳转到下一行,然后按下 C-x ) 结束宏录制
  6. C-u 11 C-x e 重复运行宏 n 次(在这种情况下为 11 次)

Eureka! 如果您没有失败,现在会得到如下结果:

(1,   I am a random text
(2,   I am not
(3,   G, youve gone mad
(4,   Click on this link
(5,   Transfer in progress (weve started the transfer process)
(6,   But transfer happened yesterday
(7,   No you are
(8,   Oh please! this is getting too much!
(9,   I love Emacs
(10,  I cant be bothered with this any more
(11,  its time to raise the bar
(12,  show me how to expand my territory

在这个时候,我将让你自己去想余下的部分。但是,在我离开之前,我想提一下有很多方法可以实现这种事情。这只是其中一种方法,而且恰好是我最喜欢的方法。

1
F3 启动宏录制(至少在我的emacs中,默认情况下),而 F4 停止录制。后续按下 F4 将播放宏。这比记住 C-x ( 等要容易得多。 - BitTickler
这个过程中单引号是如何消失的,导致文本退化的结果?在这个答案中,至少应该以某种方式解决输出中转义单引号的问题。 - Peter Mortensen

21

4

矩形选取用于简单操作,例如删除相邻行中相同数量的空格。

否则,您可以使用键盘宏。


4

谢谢您提供的链接!一张图片胜过千言万语 :)。 - allyourcode

2
上面的答案是关于在列中插入文本的。TextMate的“编辑所选行中的每一行”将相同的文本插入每一行,而不考虑每行的长度。我现在正在学习Lisp,所以我写了一个函数来实现这个功能:
(defun append-to-lines (text-to-be-inserted)
  ;;Appends text to each line in region
  (interactive "sEnter text to append: ")
  (save-excursion
    (let (point-ln mark-ln initial-ln final-ln count)
      (barf-if-buffer-read-only)
      (setq point-ln (line-number-at-pos))
      (exchange-point-and-mark)
      (setq mark-ln (line-number-at-pos))
      (if (< point-ln mark-ln)
          (progn (setq initial-ln point-ln final-ln mark-ln)
                 (exchange-point-and-mark))
        (setq initial-ln mark-ln final-ln point-ln))
      (setq count initial-ln)
      (while (<= count final-ln)
        (progn (move-end-of-line 1)
               (insert text-to-be-inserted)
               (next-line)
               (setq count (1+ count))))
      (message "From line %d to line %d." initial-ln final-ln ))))

首先选择包含您想要影响的所有行,然后使用M-x append-to-lines函数运行它。


我还没有测试过这个,但是做得很好。我更感兴趣的是“将相同的文本添加到同一列”的方法,但我相信这个也会派上用场的。 - allyourcode

2

逐步介绍如何使用矩形更改多行的前缀:

按下CTRL-x,然后再按下SPACE。这将启动“矩形模式”。
现在移动光标以选择您想要的区域 - 比如多行的第一列。

按下ALT-x并键入string-rectangle
这将启动“字符串矩形操作”,您可以在其中输入要对每行执行的操作。
(这就是@allyourcode答案中的C-x r t)。
因此,键入-。然后按enter

您将在每行上得到一个“破折号”。

您可以使用选择执行其他操作,例如删除等-请参见@allyourcode答案中的链接。

我从其他人和文档中都没有理解这个,很抱歉:)我希望有人会觉得这很有用。


-1

没有插件

添加文本

  • 开始矩形模式

    C-x SPACE

  • 将光标移动到上一个(p)或下一个(n)行

    C-p / C-n

  • 目标矩形区域

    C-x r t

  • 输入文本,然后按RET键,在所选行中添加文本

删除文本

  • 开启矩形模式

    C-x SPACE

  • 将光标移动到上一个(p)或下一个(n)行

    C-p / C-n

  • 将光标前进(f)或后退(b)按字符(C)或按行(M

    M-f / M-b

  • 删除文本:

    BACKSPACE

    C-x r k

    或者清除文本,不移动其他文本

    C-x r c


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接