instant-rename-tag.el 实时修改Tag名


#1

最近在研究VSCode好用的功能,希望通过一点点的努力, 把VSCode好的功能吸收到Emacs。

说到VSCode,说它是支持Web编程最好的IDE一点也不为过,其中实时修改Tag名字的功能非常好用。

可惜的是,Emacs一直都没有好用的实时修改Tag的功能,即使最强大的 web-mode 也需要从 minibuffer 中读取新的Tag,视线要在光标处和minibuffer来回跳动,不够爽。

以前类似的插件在原理上总是希望修改Tag的时候,实时的计算匹配的Tag区域并同步更新,这样的实现原理是有问题:

因为不管是 sgml-mode 还是 web-mode, 一旦发现Tag不匹配,就很难找到匹配Tag区域,究其原因是Emacs找到匹配的Tag区域是基于正则查找, 所以一旦Tag无法匹配,实时修改Tag的功能实现就很困难,而且在复杂的Emacs插件环境中特别容易出错。

instant-rename-tag.el 的原理

instant-rename-tag 认识到上面的问题,从实现上放弃了Tag实时匹配查找的策略,而是用下面的步骤来实现:

  1. 重命名动作触发的时候,根据 Open Tag 还是 Close Tag的位置,找到匹配的Tag区域
  2. 用 Overlay 来保存 Open Tag 和 Close Tag 的区域,一旦保存好以后,就不再进行任何Tag匹配的搜索
  3. 监控光标插入,如果当前光标是在 Tag Overlay 区域修改,比如 <div> Tag中修改,会去找 </div> 的 Overlay
  4. 找到对应的 Tag Overlay, 同步其内容

这样只在重命名启动的时候查找一下 Tag 的区域,后面只是简单的光标监控和内容同步,既实现了实时改名的功能,又不会因为Tag不匹配产生很多乱改用户buffer的问题。

Jun-26-2019%2023-37-07

安装方法见Github

使用方法

使用方法很简单, 绑定按键到 instant-rename-tag

想修改Tag名字的时候,调用一次 instant-rename-tag, 修改完成后只用把光标移动到非Tag区域继续编辑,刚刚重命名的区域会自动取消标记。


#2

想要这个功能很久了,辛苦!


#3

We need to (require sgml-mode) otherwise sgml-skip-tag-backward is undefined:

save-excursion: Symbol’s function definition is void: sgml-skip-tag-backward

PR


#4

补丁已经合并


#5

感觉这是个A-B problem:应该想办法把minibuffer的输入区域移到光标附近,这样可以一劳永逸地解决很多“还要去看远在天边的minibuffer”的问题


#6

懒猫高产啊。这功能web-mode似乎已经有了,实现方式可能不同。


#7

web-mode 我知道,但是那个需要在 minibuffer 输入 new tag名字,我觉得不够爽。 instant-rename-tag 应该是最好的原地实时修改Tag的插件,原来用的 auto-rename-tag.el ,那个实现的原理有问题,实在忍不了了,自己写一个。


#8

:+1: 如果能merge到web-mode岂不是更好?


#9

懒得merge了,自己动手丰衣足食,和别人沟通半天的精力我都可以写十个插件了。 年前给 magit 写 submodule 的功能,写代码一天搞定,合并花了我一个月的时间。

老年人了,写完代码休息去了


#10

刚刚加了一个功能:

instant-rename-tag 命令开始重命名标签,重命名完成以后,继续在重命名区域外继续编辑,重命名标记区域会自动取消,不用再次手动调用一次 instant-rename-tag 命令,智能贴心。


#11

提个建议啊 能不能不关闭 company-mode

  1. 可以在unmark的时候重新打开

  2. 在编辑的时候限制company-backends 让他只匹配tag列表中的值(当然,得有个tag列表)

    如果输入了一个没有在列表中的tag,他可以自动的添加到列表中

还是第二种方式更好些吧


#12

因为 company 也是 overlay 的机制实现的,company-mode 会干扰我的插件。 我现在是放到 let 表达式里面临时禁用的,代码运行完会自动开启 company-mode 欢迎提交更好的补丁


#13

试验了一下 干扰不是很严重

在我的环境中 只有一个company-yassnippet 一共有三个snippet: flex flex2 bison

只有一个bison选项的时候 应该还好

bison

当有多个选项的时候 关闭的tag就没有overlay了

flex

还有一个问题就是选中company之后 对应的tag没有改变

总结一下就是三个问题:

1.多个选择时,保留对应tag的overlay

2.选中company之后对应tag的修改

3.新建company-backend 及 更新candidates


#14

你的backend太少了,干扰很严重。

就是编辑Tag的时候临时禁用Company-Mode就是最简单的,其他方式都太复杂。


#15

就算backends很多 但是能用来作tag的应该不多吧

可以临时禁用无关的backends


#16

我发现一个问题就是

如果在tag的最后字符的位置 Ctrl+y ,没有达到相应的效果

我想这也是company的补全不能起作用的原因


#17

我不想把插件做的像你说的那么复杂,要不你发一个更好的PR,我觉得可以马上合并。 要不我们就不要抬杠,我认为禁用 backends 没有必要,你认为禁用 backends 好,这样没有意义。


#18

这个好像不是很好弄

需要几天时间


#19

如果你有更好的想法,你就直接发PR吧。

我这个人懒,如果一个方案太复杂,我倾向于不要用复杂方案去实现一个简单的功能。

平常重命名tag都是很简单,就打几个字符的事情,完全不需要 company-mode


#20

最新版,Tag编辑的时候会自动禁用 Company-Mode, 每次编辑完成后都会恢复 company-mode 的状态。