仅在从某个其他函数调用时才触发对函数的建议

时间:2012-10-24 19:24:26

标签: emacs elisp advising-functions defadvice

我正在尝试解决在当前和父目录dired-do-shell-command!'上无法调用.(绑定到..)的限制。堆栈跟踪粘贴在底部。

我可以定义以下建议来绕过这个错误:

(defadvice dired-get-filename (before h-no-error-if-not-filep activate)
  (ad-set-arg 1 t))

但是这会影响对dired-get-filename的所有调用。我希望它只在堆栈为dired-do-shell-command -> dired-get-marked-files -> dired-get-filename时触发。

我能想到的唯一方法如下

  • 在建议定义
  • 中搜索(with-output-to-string (backtrace))中的匹配项
  • 添加其他方法的建议以设置一些可以在建议定义中测试的变量。

有更好的方法吗?我想我正在寻找访问当前堆栈跟踪作为数据结构而不是来自(backtrace)的字符串

Debugger entered--Lisp error: (error "Cannot operate on `.' or `..'")
  signal(error ("Cannot operate on `.' or `..'"))
  error("Cannot operate on `.' or `..'")
  dired-get-filename(t)
  dired-get-marked-files(t nil)
  (let ((files (dired-get-marked-files t current-prefix-arg))) (list (dired-read-shell-command (concat "! on " "%s: ") current-prefix-arg files) current-prefix-arg files))
  call-interactively(dired-do-shell-command nil nil)

Why can dired-do-shell-command not operate on '.' or '..'?

5 个答案:

答案 0 :(得分:2)

我希望将dired-do-shell-command复制到my:dired-do-shell-command,然后从那里调用my:dired-get-marked-files,它会使用第三个参数t调用dired-get-filename

这样我可以复制/粘贴两个函数,但是我可以通过建议常用函数来减少副作用。

答案 1 :(得分:2)

您可以通过backtrace-frame一次访问一个图层的堆栈跟踪。但这真的是在推动黑客攻击。我们还建议您M-x report-emacs-bug要求!使用...

答案 2 :(得分:1)

以列表的形式访问堆栈会很棒,但不幸的是,这似乎无法从elisp中访问。 (编辑:啊,我是盲人; backtrace-frame提供了这个,我甚至没有看过它。感谢Stefan。)

第二种选择(使用额外建议和标记变量)的类似方法是根据外部建议启用或禁用内部建议。这是一个例子:

emacs follow-mode across frames

答案 3 :(得分:1)

绝对提交功能请求。

但是你的意思是你可以自己制作my:dired-do-shell-command “复制任何代码”,只需使用flet重新绑定dired-get-filename 你的功能。这接近@ oleg的解决方案。

在此question

中也进行了讨论

此代码未经测试,但您明白了。

(eval-when-compile (require 'cl))
(defun my:dired-do-shell-command (&rest args)
  (interactive)
  (let ((old-func (symbol-function 'dired-get-filename)))
    (flet ((dired-get-filename (&rest args)
                               (let ((file (funcall old-func 'verbatim)))
                                 (if (memberq file '("." ".."))
                                     (if (car args)
                                         file
                                       (expand-file-name file default-directory))
                                   (apply old-func args)))))
      (apply 'dired-do-shell-command args))))

Emacs黑客滥用defadvice太多了。它可怕地混淆了一些事情 并且只应作为最后的解决方案保留。

答案 4 :(得分:1)

使用this-command变量:

(defadvice dired-get-filename (before h-no-error-if-not-filep activate)
  (when (equal this-command 'dired-do-shell-command)
    (ad-set-arg 1 t)))