在SLIME上写代码是经常用到 Tab 键来自动补全的, 但时不时又变成了一按Tab就回到该行最前面
清空一下buffer (slime-repl-clear-buffer)
就正常了
网上搜了是有这个bug, 但是我照着做还是没解决, 再求助一下…
https://lists.gnu.org/archive/html/emacs-devel/2017-05/msg00618.html
在SLIME上写代码是经常用到 Tab 键来自动补全的, 但时不时又变成了一按Tab就回到该行最前面
清空一下buffer (slime-repl-clear-buffer)
就正常了
网上搜了是有这个bug, 但是我照着做还是没解决, 再求助一下…
https://lists.gnu.org/archive/html/emacs-devel/2017-05/msg00618.html
按TAB的时候会先缩进,然后再补全(见indent-for-tab-command
),缩进这步出错了。
缩进这步,buffer中有不平衡的括号,导致(indent--funcall-widened indent-line-function)
调用lisp-indent-line
计算出的缩进是错的,最终indent-line-to
尝试删除指定数量的字符以实现缩进,结果删除的范围包括prompt,prompt是readonly的,导致出错。
举个出错的例子:
CL-USER>
; No value
;; 输出,包含不平衡的括号
(unbalanced-paren
CL-USER> (set;在这里按TAB
建议你找出不平衡的输出,把不平衡内容周围加上 "
或者多行注释 #||#
,从而使得不平衡内容被解析成字符串或者注释,这样不会影响我们的缩进,或者把括号平衡上,再或者删除不平衡的内容,等等。最后再回去补全。
我们可以修改indent-line-function、或者搞些advice,比如在prompt line不缩进,直接补全(之后第二行会按前面的位置缩进,所以缩进会变得正常),等等,但是只要不平衡内容在,可能会有很多边界情况会出问题,所以还是按上面操作会好点。
偏题问一下,左下角的火焰icon是什么东西?
我上面的例子写错了,得写成下面这样才会出错:
CL-USER>
(unbalanced-paren
;; 输出,包含不平衡的括号
CL-USER> (set;在这里按TA
一个简单的workaround就是在prompt line的时候不缩进,直接补全,之后第二行会相对prompt line的代码缩进,所以不受之前缩进的影响,这样就不会出错了:
(defvar-local my/slime-repl-old-indent-line-function nil)
(defun my/slime-repl-at-prompt-line ()
(let ((prompt-line-range
(save-excursion
(cons (progn (goto-char slime-repl-prompt-start-mark) (point))
(progn (let ((inhibit-field-text-motion t))
(end-of-line))
(point))))))
(<= (car prompt-line-range) (point) (cdr prompt-line-range))))
(defun my/lisp-indent-line (&rest args)
(if (my/slime-repl-at-prompt-line)
'noindent
(apply my/slime-repl-old-indent-line-function args)))
(add-hook 'slime-repl-mode-hook
(lambda ()
(setq my/slime-repl-old-indent-line-function indent-line-function)
(setq-local indent-line-function #'my/lisp-indent-line)))
如果不用lispy等等包就不会出问题,我个人还是倾向于用引号或者注释包围不平衡的内容,不然感觉很多边界情况会出错。。不过如果频繁出现不平衡的内容,那还是用个workaround会比较好。
就是一个表情符号
可能我的系统不一样截图给你看到的不一样吧
感谢, 找到原因了, 原来就是因为REPL前面的括号不均衡 所以后方也受影响
估计是因为我写了一个 #/abcd $var $(+ 1 2) /#
这样的方式来解析里面的 $开头的标量或者函数(类似JS/ES6 里的反单引号语法)
还是解决不了, 按Tab就弹出错误的声音并把光标(cursor) 跳回到最前面 我就要通过清扫屏幕(slime-repl-clear-buffer)
来解决 但是我不想清扫啊…
最近真是有点烦躁了