如何更改 org-agenda-goto 的行为以在新框架中打开 org-file?

How to change the behaviour of org-agenda-goto to open org-file in a new frame?

在 org-agenda 中按 TAB (org-agenda-goto) 时,我想在新框架中打开相关的 org 文件,而不是拆分现有框架。

我可以创建一个 org-agenda-goto 的修改函数,用 switch-to-buffer-other-frame 替换 switch-to-buffer-other-window 并重新绑定 TAB-键,但我认为有更优雅的方法所以?

快速解决方案如下修改第 8 行:

(defun sk/org-agenda-goto (&optional highlight)
  "Go to the entry at point in the corresponding Org file."
  (interactive)
  (let* ((marker (or (org-get-at-bol 'org-marker)
             (org-agenda-error)))
     (buffer (marker-buffer marker))
     (pos (marker-position marker)))
    (switch-to-buffer-other-frame buffer)
    (widen)
    (push-mark)
    (goto-char pos)
    (when (derived-mode-p 'org-mode)
      (org-show-context 'agenda)
      (recenter (/ (window-height) 2))
      (org-back-to-heading t)
      (let ((case-fold-search nil))
    (when (re-search-forward org-complex-heading-regexp nil t)
      (goto-char (match-beginning 4)))))
    (run-hooks 'org-agenda-after-show-hook)
    (and highlight (org-highlight (point-at-bol) (point-at-eol)))))

我认为使用 advice 可能会更优雅地完成,但我对 emacs-lisp 的经验不多,并且不知道这究竟是如何实现的,或者如果使用 advice 会是正确的方法。

我在 override prefered method 中找到了使用 advice-add 这样的提示,以便用我自己的函数替换原来的函数:

(advice-add 'org-agenda-goto :override #'sk/org-agenda-goto)

您可以使用建议暂时使用 cl-letf 重新定义 switch-to-buffer-other-window。假设您至少使用 emacs 25.1,您可以使用 define-advice,例如

(define-advice org-agenda-goto (:around (orig-fn &rest args) "new-frame")
  (cl-letf (((symbol-function 'switch-to-buffer-other-window)
             (symbol-function 'switch-to-buffer-other-frame)))
    (apply orig-fn args)))

在建议中 orig-fnorg-agenda-goto 的占位符。或者,您可以暂时覆盖 display-buffer 的功能(您可以在此处使用许多选项——请参阅 display-buffer 的帮助),例如

(define-advice org-agenda-goto (:around (orig-fn &rest args) "new-frame")
  (let ((display-buffer-overriding-action '(display-buffer-pop-up-frame)))
    (apply orig-fn args)))