我的 company-backends
的默认值是:
(setq-default company-backends
`((company-capf ; `completion-at-point-functions'
,@(if (and (featurep 'company-tabnine)
(or (derived-mode-p 'c-mode)
(derived-mode-p 'c++-mode)))
(list 'company-tabnine))
;; :with company-semantic
;; company-gtags company-etags
:separate company-yasnippet
:separate company-tempo ; tempo: flexible template insertion
:separate company-keywords
:separate company-abbrev)
company-dabbrev-code
company-files))
我写了一个helper函数,用于给major mode hook来添加第三方的backend,以便于和我的company-backends默认值能够group起来。
这是helper函数代码:
(defun my-company-add-backend-locally (backend)
"Add a backend in my custom way.
\\(my-company-add-backend-locally 'company-robe\\)"
(make-local-variable 'company-backends)
(unless (eq (if (listp (car company-backends))
(caar company-backends)
(car company-backends))
backend)
(setf (car company-backends) ; <----- need improve here.
(cons backend (cons ':with (car company-backends))))))
这个是我改了好几次后的版本,之前是用 add-to-list
还用过其他办法。现在改成 setf
了。但是 setf
有个问题,就是会不断的叠加修改效果,尽管我设置了 company-backends
buffer local variable. 还是没用。
不知道各位大神有什么好办法么?
还是用回老办法了,cons拼装。
(defun my-company-add-backend-locally (backend)
"Add a backend in my custom way.
\\(my-company-add-backend-locally 'company-robe\\)"
(make-local-variable 'company-backends)
(unless (eq (if (listp (car company-backends))
(caar company-backends)
(car company-backends))
backend)
(cons (cons backend (cons ':with (car company-backends)))
(cdr company-backends))))
把输入值和期望的输出值提供一下,有点没明白你的意思哦
比如 company-backends
的默认值是:
((company-capf :separate company-yasnippet :separate company-tempo :separate company-keywords :separate company-abbrev)
company-dabbrev-code company-files)
当执行 (my-company-add-backend-locally 'company-elisp)
之后,我希望变成:
((company-elisp :with company-capf :separate company-yasnippet :separate company-tempo :separate company-keywords :separate company-abbrev)
company-dabbrev-code company-files)
但是这里面要判断 company-backends
里是否是 car 是否是 list, 以及 car list 里面是否第一个是 company-capf
。这样的。
具体代码逻辑 my-company-add-backend-locally
函数里写了。
主要是用了 setf
后, company-backends
会叠加,比如我进入 ruby-mode, 变成:
((company-robe :with company-capf ....) ...)
再次进入其他mode,比如 emacs-lisp-mode 后,变成了:
((company-elisp :with company-robe :with company-capf ....) ...)
这样不断叠加了。
你说的再次进入 ruby-mode 是通过 M-x ruby-mode 这样进入的吗
我试过了前面的代码,不同 buffer 里面代码是有效的
make-local-variable 只对当前 buffer 有效
通过打开一个 ruby buffer, 这个函数是从:
(add-hook 'ruby-mode-hook #'(lambda () (my-company-add-backend-locally 'company-robe)))
这种形式。
我去读 setf
的docstring,没太看懂。我以为应该是不会对 buffer-local variable 产生 全局影响的。
我觉得是 hook 有问题,如果不加 Hook, 在各个模式
手动 执行 (my-company-add-backend-locally 'company-robe) 是没有问题的
看了下 add-hook 的文档, 最后有个local的参数,
– Function: add-hook hook function &optional depth local
等下吃饭时间再试试
按道理应该不会啊,我 my-company-add-backend-locally
是设置了 make-buffer-local
的。 setf
应该修改的是 buffer local variable 才对啊。我现在修改了所有 这个hook,加上了 (add-hook ... nil 'local)
参数。试试。
xiyang
11
你应该自定义一个变量,比如
(setq my-company-backends
`((company-capf ; `completion-at-point-functions'
,@(if (and (featurep 'company-tabnine)
(or (derived-mode-p 'c-mode)
(derived-mode-p 'c++-mode)))
(list 'company-tabnine))
;; :with company-semantic
;; company-gtags company-etags
:separate company-yasnippet
:separate company-tempo ; tempo: flexible template insertion
:separate company-keywords
:separate company-abbrev)
company-dabbrev-code
company-files))
然后设置company-backends
的默认值为这个变量,这样你就可以直接操作my-company-backends
,不用再判断company-backends里的值
(defun my-company-add-backend-locally (backend)
(let* ((a (car my-company-backends))
(b (car a))
(c (cdr a)))
(make-local-variable 'company-backends)
(setq company-backends
(append
(list (append (list backend :with b) c))
(cdr my-company-backends)))))
(my-company-add-backend-locally 'company-lsp)
(my-company-add-backend-locally 'company-web)
自定义一个变量还是有一个问题,那就是很多mode其实就是 company-capf
有效。所以我用的是 setq-default
. 另外有的mode需要 my-company-add-backend-locally
两次,添加不同的 backend,比如latex下面,有很多 company backend 。当然,其实可以直接 copy 这个 default 变量出一个临时新变量也是ok的。不过原先旧的方案我用的是 cons
拼接方式。用的挺好的,就是忽然想到用 setf
结果出问题了。