我在使用irony-mode进行补全的时候,首先补全出如下,其中header是一个marked region
#include <header>
然后我在header的第一个字母前输入头文件的名字,试图覆盖掉header,有时候正常补全,有时候会直接产生一个BUG,例如我想输入一个deque:
#include <d>
产生如下bug:
我的配置如下:
(use-package cc-mode
:ensure nil
:hook (c-mode-common . (lambda ()
(c-set-style "clang")
(setq tab-width 4)
(setq c-base-office 4)))
:config
(use-package modern-cpp-font-lock
:init (modern-c++-font-lock-global-mode t))
(use-package irony
:hook ((c-mode c++-mode objc-mode) . irony-mode))
(use-package irony-eldoc
:hook (irony-mode . irony-eldoc))
(with-eval-after-load 'company
(use-package company-irony
:init (add-to-list 'company-backends 'company-irony))
(use-package company-irony-c-headers
:init (add-to-list 'company-backends 'company-irony-c-headers)))
(with-eval-after-load 'flycheck
(use-package flycheck-irony
:hook (flycheck-mode . flycheck-irony-setup)))
)
整个配置是从Prucell处fork过来的,环境是Macos10.14.1。
他的init-company处的配置我也看过了,并没有什么和这个配置冲突的地方。
求教这个是什么原因。。。
emacs编辑的时候每修改一个字符都会触发一系列hook函数,用来更新词法高亮和flycheck语法错误等,很多情况下不是很合理,比如snippet,multiple-cursor,还有iedit,自动补全等等,这些的中间输入过程触发没有意义,应该合并在一起,在最后只触发一次。我遇到过iedit因为触发频率太高导致cpu占用率极高,编辑卡顿明显
cireu
4
你歪楼了
可以给self-insert-command
函数advice, 设置一个外部计时器, 如果某一次运行该函数的时候距离上一次运行没有达到计时器所限定的值,就把post-self-insert-hook
let-bound成nil来控制触发频率.
cireu
5
我尝试着写了一个实现
(defun cm/self-insert-hook-throttler (orig-funcs &rest args)
"Delay the `post-insert-command-hook'"
(let ((post-self-insert-hook (if (> (- (float-time) cm/timer) .2)
post-self-insert-hook
nil)))
(setq cm/timer (float-time))
(apply orig-funcs args)))
(defvar cm/timer (float-time)
"Store the last time when `self-insert-command' executed")
(advice-add #'self-insert-command :around #'cm/self-insert-hook-throttler)
可能还是要把paredit之类的函数排除掉比较好,不然括号自动配对失败是一个很烦人的事情
1 个赞
谢谢,不过c-company-header我也用过,触发了别的bug………
谢谢前辈提供的实现,但是我不明白为什么会触发这个bug,以及为啥和定时器有关系?,再次感谢回答
cireu
8
其实我歪楼了,不好意思
说正经的,我就没有配置emacs写过一行的c,恐怕不能解决你的问题
btw:建议你把你的疑惑整理一下,发issue给上游,他们更有经验,不过可能对英语有要求。(首页有emacs在线英语速成,哈哈)
一般用的是before-change-hook和after-change-hook,每个插入删除和替换操作都会触发,一般使用这些hook都需要追踪每一次的更改,不能有遗漏,中间忽略几个是不行的,除非你能准确合并多个操作,把多个等效成一个,理论上是可以实现的,不过比较繁琐。
emacs编辑过程中,每插入或删除一个字符,都会触发一系列hook函数在后台做很多事情,比如cc-mode,它用这些hook来跟踪buffer的每一次修改(c-after-change),用于维护c/c++的词法高亮和缩进等内部状态,但它们对外部插件比如yasnippet和company-mode兼容可能没那么好,经常出问题,我也遇到过很多次了。
你的截图很明显就是cc-mode的hook函数c-after-change报错了,兼容性问题。一般是报bug给外部插件作者比如irony-mode。
Spdwal
12
哦哦,谢谢,我这个已经已经报了bug给了irony的作者了。。但是我看它的项目下有100多个issue还没有处理呢。。。感觉看到我这个要猴年马月了,所以先来站里问问。。