使用 advice 增强 ace-jump-mode 遇到的问题

大家好,我想用advice增强ace-jump-mode,达到 复制到指定字符 的效果 想法是用 around 增强 ace-jump-jump-to 函数(按照指定字符位置进行跳转),代码如下

;; 用于增强的函数
(defun around-copy-to(orig-fun &rest args)
  (let* (
	 (pos (nth 0 args))
	(offset (aj-position-offset pos))
        (frame (aj-position-frame pos))
        (window (aj-position-window pos))
        (buffer (aj-position-buffer pos))
        (line-mode-column 0))
    ;; 记录跳转前位置,复制中间区域
    (setq prev_point (point))
    (apply orig-fun args)
    (copy-region-as-kill prev_point offset)
    )
  )

 (defun ace-copy-mode()
  "copy from where you are to where you wanna be"
  (interactive)
  ;; 加入advice然后删除,仅在此函数中使用advice
  (advice-add 'ace-jump-jump-to :around 'around-copy-to)
  (call-interactively 'ace-jump-char-mode)
  (advice-remove 'ace-jump-jump-to 'around-copy-to)
  )
(define-key prog-mode-map (kbd "C-; c") 'ace-copy-mode)

遇到的问题是,在advice-add和advice-remove中间的块中,没有执行advice的函数(我试过增强一个el文件中的函数,是有效的),而仅使用advice-add是有效的,想问问大家是什么原因

可以用avy-zap

;; Necessary hack.
(push 'copy-region-as-kill avy-zap--function-list)

(defun avy-copy-zap-to-char ()
  (interactive)
  (let ((avy-zap-function #'copy-region-as-kill))
    (avy-zap-to-char)))
1 个赞

谢谢分享:pray: 请问你对上面问题的原因有大概的想法吗

没有,ace-jump的代码糊在一起,看不懂。而且太久没更新,我现在用avy

另外代码内部mock函数不一定要用advice

(cl-letf* ((old-fn (symbol-function 'some-func))
           ((symbol-function 'some-func)
             (lambda (args)
               (do-something args)
               (funcall old-fn args))))
  ....)

非常感谢你的分享🙏

是您头像太儒雅随和了 :joy:

4 个赞

哈哈哈😂,还是暴露了

同样推荐用 avy,ace-jump 被我前面抛弃了,任何依赖于它的都抛弃了

谢谢分享,主要想分析一下原因,正在试着debug

因为 advice-remove 过早执行了,ace-jump-char-mode 的效果在 ace-copy-mode 完全执行完才开始,不信的话,试试加个 message:

(call-interactively 'ace-jump-char-mode)
(message "Removing advice...")
(advice-remove 'ace-jump-jump-to 'around-copy-to)

非常感谢,你说的没错,ace-jump-char-mode不是一定会执行 ace-jump-jump-to,所以advice没生效

给大家复现以下这个问题的原因 背景是: ace-jump-jump-to 是 ace-jump-mode 执行跳转的函数,所以用advice记录执行前后的光标位置,然后复制之间的区域的思路是可行的 问题在于,ace-jump-char-mode并不是每次调用都会执行 ace-jump-jump-to,其执行过程如下(以下为ace-jump-char-mode的主要方法ace-jump-do)

以上代码证明,ace-jump-char-mode执行完后,可能只是改变了键位的绑定函数,并没有直接执行跳转,点击键位触发跳转时,advice-remove已经执行,所以advice没生效

我的处理方式是,增强时,只执行advice-add,不删除,这样advice的效果会一直存在。 为了不影响原来的ace-jump-char-mode执行,绑定char-mode键位时,执行一个lambda,先删除advice,再执行char-mode函数