我在符号里发现有小写的上标数字,如果能把每一个括号都加上数字标志,那么lisp程序不就更容易排错了。希望emacs高手给提供一个工具。
可以看看rainbow-delimiters 这个是用颜色标记不同层次的括号。
用上标符号标注的话会改变排版,估计会显得比较怪。
另外可以配合show-paren-mode (emacs自带)使用。
试着写了一个,测试了一下,还可以用。
rainbow-delimiters
给所有的括号都加上颜色,highlight-parentheses-mode
会把当前cursor周围的几层括号用比较鲜艳的颜色标出来,两个一起用效果更好。
昨天晚上在梦里看过你写的代码,风格比较粗暴,也可以试试 parse-partial-sexp
函数。
对于日常使用,括号上的层次标号提高不了多少编辑效率,反而会干扰你的注意力。可能适用于超长函数分割成两个 window 浏览这种情况。
在 rainbow-delimiters
基础上做了一个简单的实现,代码就不上了。仅贴一张核心函数效果图,可以当成伪码来看:
可以看出还存在一些问题:
-
由于用了默认的配置,上标的字体没有选好,没有做到等宽,请无视。
-
代码宽度大大增加,十层以上的时候更明显。
-
代码缩进量不对,
split-line
时缩进也不对。其根源应该是 char-width 的问题,解决方案大概有-
改
calculate-lisp-indent
补偿上一行的括号数,这个不太熟,感觉有点难搞。 -
让 text properties 支持
char-width
属性,但目前不支持?
-
总之,个人感觉这个功能不怎么实用
可以考虑用 font-lock 直接把左括号显示成彩色底色的数字,右括号变成对应的颜色,2 和 3 就不用解决了。
实际上这个也不只是辅助读代码的作用,更近一步可以做成以 Sexp 为单位的快速跳转,我觉得是有前途的
超过 10 层怎么显示呢,类似于 glyphless-char
这种框框么?
我觉得就算照顾一下终端用户 10 个数字再加 26 个字母应该足够了,只在当前所在的顶层 sexp 开始显示。
用渐变颜色可能也是一种办法。
纯底色是有可能和一些高亮相冲突,到时候就分不清了,用渐变会不会太花了。
不知道可不可以用 composition
属性来做上下排列的数字。
而且用户需要花点时间才能适应这种表示方法吧,习惯很难改变。
我用 compose-region
实现了一个, 放在正下方, 这样等宽但高度有些奇怪
(defun rainbow-delimiters--number-to-subscript (char n)
(cond ((< n 0))
((< n 10)
(list char '(bc . tc) (+ ?₀ n)))
((< n 100)
(list char '(bc . tc) (+ ?₀ (/ n 10)) '(bc . tc) (+ ?₀ (mod n 10))))))
(defun rainbow-delimiters--add-depth-number (loc depth match)
(let* ((char (char-after loc))
(pair-string (char-to-string char)))
(when-let (components (rainbow-delimiters--number-to-subscript char depth))
(compose-region loc (1+ loc) components))))
(advice-add 'rainbow-delimiters--apply-color
:after #'rainbow-delimiters--add-depth-number)
除非为了跳转,把所有括号都标出来反而模糊了焦点,编辑状态下,标识出当标所在位置的层级就够了。
感谢你的建议,其实这个想法主要是在修改一个大函数时不小心缺少括号提出的需求。其实只要当前函数定义中看一下括号层数,容易找到逻辑错误。所以你的建议很好。
(defun disp-num-brackets()
"raplace brackets by number superscript at new buffer."
(interactive)
(search-backward "(")
(setq my-point (point))
(forward-sexp)
(let ((my-str (buffer-substring-no-properties my-point (point))))
(setf new-str (get-temp-num-brackets-string my-str))
(generate-new-buffer "*my-number-brackets*")
(set-buffer "*my-number-brackets*")
(set-window-buffer (selected-window) (current-buffer))
(insert new-str)))
谢谢大家的探讨,最终写出了针对指定s表达式的数字上标括号程序,解决了我的问题。加上(show-paren-mode)基本解决了问题。特别感谢YangZhao11、fontux、yyjjl、twlz0ne.
忘记了是哪本书上说: lisp看的是缩进