consult 构建正则的函数不再在外部接收参数后,如何使用 advice 处理其在内部 lambda 接收的参数?

事情的起因是 consult 的这条 commit

consult-ripgrep 为例

这条 commit 之前,consult--ripgrep-builder 的行为是接受一个参数 input 作为搜索的字符串

我想让它支持中文搜索,做法是

(advice-add 'consult--ripgrep-builder :filter-args #'my--consult-zh-builder))

其中 my--consult-zh-builder 就是先对输入的 input 做处理,变成一个能搜索中文的正则,然后把处理完的 input 再发给 consult--ripgrep-builder 让它构建相关表达式

合并了最上面提到的 commit 之后,consult-ripgrep 处理 input 的方式变成了在构建正则时不接受外部参数,而是在内部处理

可以看到在内部定义了一个 lambda 去接收相关的 input

对于这种情况,有办法修改在 consult--ripgrep-make-builder 内部所接受的 input 值吗?

可以把整个函数复制出来,修改之后再用 override advice

那感觉好费劲,复制出来后如果上游更新了,自己也得跟着更新

在 Windows 上我就用 consult-find-winconsult-find 给 override 了,如果啥都要自己维护感觉精力实在分不过来

看来是没啥更好的办法了,再咋 advice 没参数也没办法 advice 是不是

看了下代码,应该按照 consult 的逻辑扩展一下就可以,不需要写 advice。

(defun my-make-ripgrep-zh-builder ()
  (let ((ripgrep-builder (consult--ripgrep-make-builder)))
    (lambda (input)
      (funcall ripgrep-builder (my--consult-zh-builder input)))))

(defun my-consult-ripgrep (&optional dir initial)
  (interactive "P")
  (consult--grep "Ripgrep" (my-make-ripgrep-zh-builder) dir initial))
2 个赞

谢谢,试了试这种方法的确可行;但是要自己写 my-consult-* 这一类函数

好烦,不如之前写个 advice 然后啥都能用

今天在 consult 的 issue 区看到了提出的类似问题,作者回复:可以修改 *-builder 返回的值,但更推荐的是既然是修改正则,不如直接修改 consult--default-regexp-compiler 返回的结果

这样改的确可以说是一劳永逸了


顺便附上修改之后的结果

(defcustom my-consult-py-prefix ?:
  "The prefix character when using consult to search Pinyin."
  :group 'consult
  :type 'character)

(defun my--consult-py-regexp-compiler (input type ignore-case)
  "Compile the INPUT string to a list of regular expressions.

The function should return a pair, the list of regular expressions and a
highlight function. The highlight function should take a single
argument, the string to highlight given the INPUT. TYPE is the desired
type of regular expression, which can be `basic', `extended', `emacs' or
`pcre'. If IGNORE-CASE is non-nil return a highlight function which
matches case insensitively."
  (require 'pinyinlib)
  (setq input (consult--split-escaped
               (if (char-equal my-consult-py-prefix (string-to-char input))
                   ;; Detect the first entered character. If it matches
                   ;; `my-consult-py-prefix', convert the subsequent
                   ;; characters into Pinyin regexp.
                   (pinyinlib-build-regexp-string (substring input 1))
                 input)))
  (cons (mapcar (lambda (x) (consult--convert-regexp x type)) input)
        (when-let (regexps (seq-filter #'consult--valid-regexp-p input))
          (apply-partially #'consult--highlight-regexps regexps ignore-case))))

(advice-add 'consult--default-regexp-compiler :override #'my--consult-py-regexp-compiler)

实际上就是 cireu 大佬所说的复制出来后 override,但毕竟只需要维护一个,就轻松多了

唯一的问题是在 Windows 下使用 consult-findconsult-grep 有些小毛病,会把不匹配的结果也输出出来,匹配到的结果会做高亮处理(在 wsl 下测试一切正常,未出现 Windows 上的这些问题)

但常用的 consult-ripgrepconsult-fd 使用都正常,所以上面那些小毛病就不处理了(估计是 Windows 的问题,折腾也白耗心神。。。)