如何在同一窗口中执行Emacs grep-find链接?

9

当我使用grep-find时,它会打开另一个窗口(框架中的区域),显示一份结果列表供选择。当我选择其中一个时,它会在与grep-find不同的窗口中打开目标文件。

如何使目标文件在同一窗口中打开(取代grep结果窗口,并显示我实际所需的内容)?

如何防止grep-find打开单独的窗口(让它在当前窗口中打开)。我的目标是,在同一窗口中查找内容,找到后直接跳转,不需要切换窗口。我想将这个功能加入我的.emacs文件。

4个回答

6

看起来没有办法配置compile 包以实现您要求的功能。而且,使用advice调整其行为也没有简单的方法。我认为您必须编辑实际跳转到错误的函数,您可以通过以下方式将其添加到您的 .emacs 文件中来完成此操作(在 Emacs 23.1 中测试):

(eval-after-load "compile"
'(defun compilation-goto-locus (msg mk end-mk)
  "Jump to an error corresponding to MSG at MK.
All arguments are markers.  If END-MK is non-nil, mark is set there
and overlay is highlighted between MK and END-MK."
  ;; Show compilation buffer in other window, scrolled to this error.
  (let* ((from-compilation-buffer (eq (window-buffer (selected-window))
                  (marker-buffer msg)))
     ;; Use an existing window if it is in a visible frame.
     (pre-existing (get-buffer-window (marker-buffer msg) 0))
     (w (if (and from-compilation-buffer pre-existing)
        ;; Calling display-buffer here may end up (partly) hiding
        ;; the error location if the two buffers are in two
        ;; different frames.  So don't do it if it's not necessary.
        pre-existing
      (let ((display-buffer-reuse-frames t)
        (pop-up-windows t))
        ;; Pop up a window.
        (display-buffer (marker-buffer msg)))))
     (highlight-regexp (with-current-buffer (marker-buffer msg)
             ;; also do this while we change buffer
             (compilation-set-window w msg)
             compilation-highlight-regexp)))
;; Ideally, the window-size should be passed to `display-buffer' (via
;; something like special-display-buffer) so it's only used when
;; creating a new window.
(unless pre-existing (compilation-set-window-height w))

(switch-to-buffer (marker-buffer mk))

    ;; was
;; (if from-compilation-buffer
;;     ;; If the compilation buffer window was selected,
;;     ;; keep the compilation buffer in this window;
;;     ;; display the source in another window.
;;     (let ((pop-up-windows t))
;;       (pop-to-buffer (marker-buffer mk) 'other-window))
;;   (if (window-dedicated-p (selected-window))
;;       (pop-to-buffer (marker-buffer mk))
;;     (switch-to-buffer (marker-buffer mk))))
;; If narrowing gets in the way of going to the right place, widen.
(unless (eq (goto-char mk) (point))
  (widen)
  (goto-char mk))
(if end-mk
    (push-mark end-mk t)
  (if mark-active (setq mark-active)))
;; If hideshow got in the way of
;; seeing the right place, open permanently.
(dolist (ov (overlays-at (point)))
  (when (eq 'hs (overlay-get ov 'invisible))
    (delete-overlay ov)
    (goto-char mk)))

(when highlight-regexp
  (if (timerp next-error-highlight-timer)
      (cancel-timer next-error-highlight-timer))
  (unless compilation-highlight-overlay
    (setq compilation-highlight-overlay
      (make-overlay (point-min) (point-min)))
    (overlay-put compilation-highlight-overlay 'face 'next-error))
  (with-current-buffer (marker-buffer mk)
    (save-excursion
      (if end-mk (goto-char end-mk) (end-of-line))
      (let ((end (point)))
    (if mk (goto-char mk) (beginning-of-line))
    (if (and (stringp highlight-regexp)
         (re-search-forward highlight-regexp end t))
        (progn
          (goto-char (match-beginning 0))
          (move-overlay compilation-highlight-overlay
                (match-beginning 0) (match-end 0)
                (current-buffer)))
      (move-overlay compilation-highlight-overlay
            (point) end (current-buffer)))
    (if (or (eq next-error-highlight t)
        (numberp next-error-highlight))
        ;; We want highlighting: delete overlay on next input.
        (add-hook 'pre-command-hook
              'compilation-goto-locus-delete-o)
      ;; We don't want highlighting: delete overlay now.
      (delete-overlay compilation-highlight-overlay))
    ;; We want highlighting for a limited time:
    ;; set up a timer to delete it.
    (when (numberp next-error-highlight)
      (setq next-error-highlight-timer
        (run-at-time next-error-highlight nil
                 'compilation-goto-locus-delete-o)))))))
(when (and (eq next-error-highlight 'fringe-arrow))
  ;; We want a fringe arrow (instead of highlighting).
  (setq next-error-overlay-arrow-position
    (copy-marker (line-beginning-position)))))))

eval-after-load 部分仅确保您在 Emacs 定义之后重新定义它,以便您的更改生效。


Trey,你的函数能否进行调整,使Shift加鼠标单击在同一缓冲区中打开,而不是保持相同的鼠标单击行为以在新窗口中打开? - SFbay007
1
@Ammari 不是很简单。一种hack的方法是为Shift-mouse创建一个新的绑定,以本地设置变量(let ((use-same-window t)) ...),然后发出跳转到错误的命令,在上面的函数中选择您想要的行为。 - Trey Jackson

1
您可以添加一个绑定(例如Alt-m),然后执行以下操作。
(define-key grep-mode-map "\M-m" (lambda() 
                                   (interactive) 
                                   (compile-goto-error)
                                   (delete-other-windows)
                                   (kill-buffer "*grep*")))

我找不到一种方法来用自定义函数替换标准的“Enter”/鼠标点击绑定。

1
标准的回车/鼠标点击绑定是缓冲区子字符串的文本属性,您可以编辑该属性,或更改编译添加该属性的方式。 - Justin Smith

1
另一种方法是:

(defun eab/compile-goto-error ()
  (interactive)
  (let ((cwc (current-window-configuration)))
    (funcall
     `(lambda ()
        (defun eab/compile-goto-error-internal ()
          (let ((cb (current-buffer))
                (p (point)))
            (set-window-configuration ,cwc)
            (switch-to-buffer cb)
            (goto-char p ))))))
  (compile-goto-error)
  (run-with-timer 0.01 nil 'eab/compile-goto-error-internal))

0

我曾经有同样的问题,后来在emacs.stackexchange找到了这个答案https://emacs.stackexchange.com/a/33908/20000

(defun my-compile-goto-error-same-window ()
  (interactive)
  (let ((display-buffer-overriding-action
         '((display-buffer-reuse-window
            display-buffer-same-window)
           (inhibit-same-window . nil))))
    (call-interactively #'compile-goto-error)))

(defun my-compilation-mode-hook ()
  (local-set-key (kbd "o") #'my-compile-goto-error-same-window))

(add-hook 'compilation-mode-hook #'my-compilation-mode-hook)

*grep*缓冲区中按下o将在同一帧中打开位置和文件。
我发现这是一个优雅的解决方案,不需要删除框架或太多的Lisp代码,只需钩入compilation-mode-hook即可。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接