大家是怎么实现多重修改(多重光标)的?

之前我用过sublime text,对多重光标印象很深。 用Emacs之后尝试了evil-mc和evil-multiedit,体验并不完美。

多重光标的使用场景大概可以归为三种,

  1. 在不同位置修改同一个单词
  2. 修改一个矩形区域
  3. 没有明确规律的各个地方,类似 求教如何配置,使用鼠标添加选中 楼主演示的这种

evil-mc和evil-multi-edit应用的的都是第一种场景:选中各个单词然后插入光标进行编辑。然而事实上这种操作完全是可以用Emacs自带的query-replace完成的。更进一步,query-replace把选中-修改两步操作合并为一个,只要声明要进行的操作然后决定替换(y)还是跳过(n)就好了。这个博主跟我的想法差不多。

对于第二种场景,Emacs和evil都有矩形选择,我就不多说了。

第三个场景是目前空白的(看起来像是,反正我没看见过):用鼠标或是命令插入光标,然后启动multi cursor开始编辑。或许以后会有人实现?

你们平时需要多重修改的时候是怎么搞的?有没有什么奇技淫巧?

这是我配置里query replace的helper 函数(helper 函数用中文怎么说?帮助函数?)超好用 :smiley:

(define-key evil-normal-state-map "Q" #'moon/query-relace-point)
(define-key evil-visual-state-map "Q" #'moon/query-replace-region)

;;;###autoload
(defun moon/query-replace-region ()
  "Query replace selected region."
  (interactive)
  (query-replace (buffer-substring-no-properties
                  (region-beginning)
                  (region-end))
                 (completing-read "Replace to: " ())
                 ))

;;;###autoload
(defun moon/query-relace-point ()
  "Query replace thing at point."
  (interactive)
  (let ((word (thing-at-point 'word t)))
    (query-replace word
                   (completing-read (format "Replace \"%s\" to: " word) ())
                   nil (beginning-of-line))))
1 个赞

多光标的使用情景总结挺好的。

前两个场景 Vim 和 Emacs 体验还算行,但第三个场景不得不说 Sublime Text 做的是最好的。

我目前主要是在 Vim 里使用 cgn 命令,多光标实际使用的较少。


楼主链接到 medium 上的那篇文章,我之前碰巧翻译过。不方便访问 medium 网站的同学可以看我这篇译文: 【译】Vim 不需要多光标编辑功能

我来举一则多重光标破功的例子。

有这样一段文本:

b40b7e799deabac916d631d181a7f19f3060acc5 third_party/doctest (1.2.7-2-gb40b7e7)
2c35b5e7251ab5d364b1b3164eccef7b5d2293c5 third_party/loguru (v1.7.0-6-g2c35b5e)
208595b2620cf6260ce3d6d4cf8543f13b206449 third_party/msgpack-c (cpp-1.3.0-321-g208595b2)
daabb88e001f562e1f7df5f44d7fed32a0c107c2 third_party/rapidjson (v1.1.0-318-gdaabb88e)
1ca7189fe81ee8c59bf08196852f70843a68a63a third_party/sparsepp (1.1-11-g1ca7189)

想要变成:

"doctest"   => "b40b7e799deabac916d631d181a7f19f3060acc5",
"loguru"    => "2c35b5e7251ab5d364b1b3164eccef7b5d2293c5",
"msgpack-c" => "208595b2620cf6260ce3d6d4cf8543f13b206449",
"rapidjson" => "daabb88e001f562e1f7df5f44d7fed32a0c107c2",
"sparsepp"  => "1ca7189fe81ee8c59bf08196852f70843a68a63a",

看起来是很适合多重光标的场景,但是中间有个单词出现 - 导致移动步调不一致:

emacs-multiple-cursor_optm

这已经算是比较理想的情况了,如果再复杂一点,一行当中出现多个编辑点,或者 y(选中)n(跳过) 圈定了一大段内容(甚至超出了屏幕),根本无法准确控制&知道按下方向键(或删除等其它键)之后,光标的正确位置,只要一个编辑点出错,全功尽弃。

鼠标选择……:More emacs configuration tweaks (multiple-cursor on click, minimap, code folding, ensime eval overlays)

我好像从来没有碰到 几个要加cursor的地方完全没关系 的情景。。。

2 个赞

碰到这种情况,你可以把 - 连接的两个/多个词定义为一个词语。比如 Vim 里这样使用:

setlocal iskeyword+=-  "使用 local 则只对当前 buffer 生效

这样之后,既然都是同一类文本对象,移动的步调就一致了。

之前使用 evil 的时候,记得看到过类似的选项。你可以找一下。


刚在 Vim 又试了一下,因为你的例子两边都有空格。使用 BE 也是可以的,步骤比以上更简单了。

我主要是想说明多重光标可能遇到的状况。如果仅仅是编辑选中的字词,不会有太大问题,如果还要编辑选中字词前后的内容,就要面对各种情况,不光是-,还有其它各种导致混乱的连接符号,防不胜防。

一旦出错,无法停下来修正单个编辑的光标位置。

一旦出错,不能很好的停下来修正,确实是个问题。

不过正如我上面说的,按 E:rofl: 其它情况就只能具体问题具体分析了。多光标还是解决了一些问题的,没有它之前,这些个情况就只能用脚本宏或者查找替换了吧?恐怕只能更麻烦。

它能解决一些问题,但是不能指望它解决所有问题。

我觉得暂时对单个光标进行操作的功能应该很有用。或许可以造个轮子把这些功能实现了?话说多重光标已经有了至少四个不同的轮子了,是我知道的轮子最多的一个 :joy:

我想起 Sublime Text 有个 powercusor 的插件(好像叫这名字?我现在 manjaro 下,没安装 Sublime Text)。

效果是:是可以像图钉一样在 buffer 里到处放光标 :joy: 然后可以选择激活它们一起联动,或者不理会,只关注当前这个光标。

应该就是你们想要的效果?

这个感觉还不如用替换来解决。。如果用doom的配置的话

:`<,`>s/\(.*\) .*\/\(.*\) (\(.*\))/"\2" => "\1" #evil replace
:al => #align use pattern "=>"

minibuffer里开了smartparens,括号会自动escape,打起来也不是很麻烦

如何实现「批量修改」,得根据具体的情况,以下

  • 手动重复几次就完了
  • C-x ( (kmacro-start-macro)
  • C-M-% (query-replace-regexp)
  • M-x align
  • C-x SPC (rectangle-mark-mode)
  • Sed/Awk/Emacs Lisp/etc

都有「批量修改」效果,我没用过「多光标」,对它也不了解。自己分析规律,再用基本的工具来解决需求,对我来说是个乐趣。

你举的这个例子规律非常明显,如果是我的话,就用 RegExp。

配合合适的按键绑定, @twlz0ne 的这个具体问题是很轻易解决的 。当然,我的另外一个目的是尝试下 manjaro 下的录屏操作 :rofl:

开头结尾那个 Super + h/l 是 i3 的切换窗口操作,大家忽略就好。