在defadvice没有在函数之前执行之前?

时间:2012-03-05 23:06:16

标签: emacs elisp

[我为糟糕的头衔道歉,但无法想出更好的头衔。]

bin chen在Google +上询问:

  

如何在#emacs中M-!后的迷你缓冲区中输入(buffer-file-name)的相对路径?

我想如果buffer-file-name保存在寄存器中,则应该在insert-register提示符处调用shell-command Cx ri )来访问它。

(defun save-buffer-file-name-in-register ()
    (set-register ?F (buffer-file-name))
    (set-register ?D (file-name-directory buffer-file-name)))

(defadvice shell-command (before save-buffer-file-name)
  "Save buffer-file-name to register F before running shell-command"
  (save-buffer-file-name-in-register))

(ad-activate 'shell-command)

当我调用shell-command M - !)后跟insert-register Cx ri )时,收到错误消息:{{ 1}}。

但是当我运行Register does not contain any text时,我确实看到寄存器list-registersF设置了适当的值。如果我再次运行D,我可以访问先前保存的寄存器中的值。

寄存器第一次设置得太晚了吗?如何修复代码以执行我想要的操作?

修改:将shell-command更改为around(感谢@phils)

2 个答案:

答案 0 :(得分:2)

n.b。您已定义around建议,而不是before建议。

Around通知充当包装器,并且必须包含令牌ad-do-it以执行它正在包装的函数的代码。

您通过调用shell-command

有效地替换了save-buffer-file-name-in-register函数的正文

关于你的主要问题,我需要检查文档,但我怀疑因为建议函数的参数可用于建议,原始函数的interactive声明可能在建议之前执行,这可以解释为什么你的寄存器值在交互式shell命令提示符下不可见。

(如果上面代码中的around确实是您正在使用的,那么您仍然被提示输入shell命令的事实似乎会验证此序列。)

答案 1 :(得分:2)

当交互式表单运行时,您的建议尚未执行。请参阅:此question

如果您希望坚持使用此方法,则需要在建议中指定一个重新定义原始内容的交互式表单。然而,这种方法对于花哨的裤子来说有点花哨。

只需定义您自己的交互式功能,无需注册即可完成您想要的任务。

(defun insert-cur-dir ()
  (interactive)
  (let ((dir-name (file-name-directory (buffer-file-name (window-buffer (minibuffer-selected-window))))))
    (insert (or dir-name ""))))

(define-key minibuffer-local-map (kbd "C-c i") 'insert-cur-dir)

另一种方法是使用yasnippet