分享一个elisp修改 buffer 时常见的错误,不应该犯的,大家引以为戒

写了一段elisp,如下,

(save-excursion 
  (goto-line 2) 
  (let ((found nil)) 
  (while (and (not found) (<= (line-number-at-pos) 90) (not (eobp)))
    (if (looking-at "^[[:space:]]*if(0){")
        (progn (kill-line)(insert "if(1){")
               (indent-for-tab-command)(setq found t) )
      (if (looking-at "^[[:space:]]*if(1){")
          (progn (kill-line)(insert "if(0){")
                 (indent-for-tab-command)(setq found t) ) )
          )
    (forward-line 1))
    ))

功能是在emacs中运行脚本后,检查脚本中的 if(0){ 修改成if(1){或者反过来。这样脚本运行数据就直接放脚本里了,不用另外找地方。

然而elisp没学好,为了简单方便,我直接kill-line,删除整行后在插入。结果我用了hs-hide-all代码折叠,运行后直接把代码给删了。

正确办法之一是用(replace-match "if(1){" nil nil nil 0)修改当前匹配,这样就安全了

1 个赞

这个贴子大家忽略吧,bug百出,我用(replace-match "if(1){" nil nil nil 0) 就以为改好了,没问题了,结果今天总感觉那里不对,最后才发现,(forward-line 1)这个也是不能用的,虽然不会误删代码,但会跳过代码段

挺好的呀,在错误里学习,多写写多想想,说不定就成长为 Elisp 高手了。

写正则可以考虑用 rx,当正则比较复杂的时候,rx 的可读性会更好一些,后面容易维护一些。

另外如果类似的 if 判断比较多的话,也可以考虑用 cond ( 17. Basic control flow with if, cond, and others) 去写。

讓ai給review一下先 :laughing::laughing:

倒反天罡了, 应当是先让ai写一版, 然后给ai review, 最后发现错漏百出(完美无瑕), 发帖吐槽ai真不行(太强了)

不至于啊不至于,其实只是打破了一个 if(X){ 这个东西整行出现的基本假设嘛,那对应的地方肯定都要改,到目前为止还只是“bug 二出”对吧?

另外不知道是否打算:1 考虑大括号没有紧跟小括号的情况 if(X) {,或者小括号没有紧跟 if 的情况 if (X) {;2 考虑 if 后面是单个语句,没有大括号的情况 if (X) stmt; 呢?如果按照“正则表达式匹配,捕获 if 后面小括号里面的内容,将 01 交换后,使得光标恰好停在匹配部分之后”的思路,我想 re-search-forward + replace-match 很有可能满足此需求 :smiling_face_with_three_hearts:

:sob: rx 是将正则从“机话”变成“人话”的伟大发明