非常感谢懒猫的回复以及写的 lsp-bridge ,用了这个包之后,Emacs 变得非常流畅。
我已经根据意见修改了 acm-get-input-prefix 相关内容:
diff --git a/acm/acm.el b/acm/acm.el
index 7c1f9d6..cb38823 100644
--- a/acm/acm.el
+++ b/acm/acm.el
@@ -373,7 +374,13 @@ So we use `minor-mode-overriding-map-alist' to override key, make sure all keys
(defun acm-get-input-prefix ()
"Get user input prefix."
- (let ((bound (acm-get-input-prefix-bound)))
+ (let* ((acm-input-bound-style (if (and acm-enable-org-roam
+ (eq major-mode 'org-mode)
+ (not (org-in-src-block-p))
+ (org-in-regexp org-roam-bracket-completion-re 1))
+ "symbol"
+ "ascii"))
+ (bound (acm-get-input-prefix-bound)))
(if bound
(buffer-substring-no-properties (car bound) (cdr bound))
"")))
不确定这种写法是否标准,修改以后是可以正常获得补全,但是展开时仍存在问题,因为 acm-update 独立获取了 bounds,见最后一行:
(defun acm-update (&optional candidate)
(acm-quick-access-init)
(let* ( ;; variables...
(bounds (acm-get-input-prefix-bound))) ;; <- 这里
需要再修改 acm-update 中的代码,相当于把条件写了三处地方,如果封装成一个和 acm 核心功能无关的判断函数又感觉怪怪的。在进一步修改之前,我想再次征求一下意见。
目前我想到以下几种方案:
- 同时修改上面所有地方。
- 修改
acm-get-input-prefix-bound,需要考虑到代码中的其他部分,如 lsp-bridge-set-prefix-style。 - 修改
acm-update和acm-update-candidates,比如在acm-update中获取 bounds,再传给acm-update-candidates。
以上方案都存在一个问题:org-roam 中有另一个默认关闭的功能 org-roam-complete-everywhere 允许用户在链接外的任意位置补全(示例),也许会有用户想要这个功能。我看了一些回复和 commit,默认使用 symbol 会出现一些问题。 要解决这个问题,可以像之前的回复提到的让每一个后端自定义边界函数。
这是 org-roam 中 capf 的实现:
(defun org-roam-complete-link-at-point ()
(let (roam-p start end)
(when (org-in-regexp org-roam-bracket-completion-re 1)
(setq roam-p (not (or (org-in-src-block-p)
(string-blank-p (match-string 1))))
start (match-beginning 2)
end (match-end 2))
(list start end
(org-roam--get-titles)
:exit-function
;; body
))))
(add-hook 'completion-at-point-functions f nil t)
这一函数内部用正则获取边界后返回 (START END COLLECTION . PROPS) ,前两个参数就是所用的边界。对于最终用户来说,仍旧不需要进行额外的配置,而对于开发者来说,可以减少许多 workaround。
当然,实现这个想法会影响到许多代码,我自己用不到 org-roam-complete-everywhere ,暂时打算先用前面几种方案实现基础功能。
我自己写代码的速度还不够快
,目前 fork 了仓库,想等功能稳定和充分测试后再提交 PR。