Mirroring location in file in two opened buffers side by side - emacs

I am trying to find a package/function in emacs where it would have both files opened side by side to be at same line location mirroring the movement of whichever buffer is moving.
Meaning, for two buffers opened side by side, moving in one of the buffers (page up/down, moving cursor.,..etc) would have the same movements in the other buffer.
More specifically, when opening a buffer (and while activating this mode) the opened buffer should already be at the line position of the one that is already opened in the other buffer window.

You could try scroll-all-mode. This switches on parallel scrolling of all windows of one frame.
Scrolling with the mouse and scroll bar do not work for me. But all scrolling with keys (such as Pg-Down, Pg-Down and cursor movements) works fine.
EDIT:
You could also try the following code. It works only for a frame with exactly two windows not counting the minibuffer. You have to open the files at first and make sure that they are shown in two windows side-by-side. Then define the master window by activating sync-window-mode for it. Make sure that line-wrapping is off for both windows.
EDIT: Fixed a problem (sometimes one had to press buttons twice to sync).
Solution: Also hook to window-scroll-functions. At post-command-hook the right window-start position is not known since redisplay did not run yet. The fist point where the future window-start is known is at window-scroll-functions.
(defun sync-window (&optional display-start)
"Synchronize point position other window in current frame.
Only works if there are exactly two windows in the active wrame not counting the minibuffer."
(interactive)
(when (= (count-windows 'noMiniBuf) 2)
(let ((p (point))
(start (or display-start (window-start)))
(vscroll (window-vscroll)))
(other-window 1)
(goto-char (min (max p (point-min)) (point-max)))
(set-window-start (selected-window) start)
(set-window-vscroll (selected-window) vscroll)
(other-window 1)
)))
(define-minor-mode sync-window-mode
"Synchronized view of two buffers in two side-by-side windows."
:group 'windows
:lighter " ⇕"
(if sync-window-mode
(progn
(add-hook 'post-command-hook 'sync-window-wrapper 'append t)
(add-to-list 'window-scroll-functions 'sync-window-wrapper)
(sync-window))
(remove-hook 'post-command-hook 'sync-window-wrapper t)
(setq window-scroll-functions (remove 'sync-window-wrapper window-scroll-functions))
))
(defun sync-window-wrapper (&optional window display-start)
"This wrapper makes sure that `sync-window' is fired from `post-command-hook'
only when the buffer of the active window is in `sync-window-mode'."
(with-selected-window (or window (selected-window))
(when sync-window-mode
(sync-window display-start))))
(provide 'sync-window)
Next, a version that synchronizes lines instead of character positions.
If you select some lines in the master buffer this also marks the corresponding lines in the slave buffer. The highlighting keeps permanent until you select another region in the master buffer. It even survives deactivation of sync-window-mode in the master buffer. You get ride of the highlighting by
M-x sync-window-cleanup
in the slave buffer.
(defface sync-window-face ;; originally copied from font-lock-function-name-face
'((((class color) (min-colors 88) (background light)) (:foreground "Yellow" :background "Blue1"))
(((class color) (min-colors 88) (background dark)) (:foreground "Red" :background "LightSkyBlue"))
(((class color) (min-colors 16) (background light)) (:foreground "Blue" :background "Yellow"))
(((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue" :background "Yellow"))
(((class color) (min-colors 8)) (:foreground "blue" :bold t))
(t (:bold t)))
"Face used to highlight regions in `sync-window-mode' slaves."
:group 'sync-window)
(defvar sync-window-overlay nil
"Overlay for current master region in `sync-window-mode' slaves.")
(make-variable-buffer-local 'sync-window-overlay)
(defun sync-window-cleanup ()
"Clean up after `sync-window-mode'."
(interactive)
(if (overlayp sync-window-overlay)
(progn
(delete-overlay sync-window-overlay)
(setq sync-window-overlay nil))
(remove-overlays (point-min) (point-max) 'sync-window-slave t)))
(defvar sync-window-master-hook nil
"Hooks to be run by `sync-window' in the master window ")
(defun sync-window (&optional display-start)
"Synchronize point position other window in current frame.
Only works if there are exactly two windows in the active wrame not counting the minibuffer."
(interactive)
(when (= (count-windows 'noMiniBuf) 2)
(let ((p (line-number-at-pos))
(start (line-number-at-pos (or display-start (window-start))))
(vscroll (window-vscroll))
breg ereg)
(when (use-region-p)
(setq breg (line-number-at-pos (region-beginning))
ereg (line-number-at-pos (if (looking-back "\n") (1- (region-end)) (region-end)))))
(run-hooks 'sync-window-master-hook)
(other-window 1)
(goto-char (point-min))
(when breg
(sync-window-cleanup)
(overlay-put (setq sync-window-overlay (make-overlay (line-beginning-position breg) (line-end-position ereg))) 'face 'sync-window-face)
(overlay-put sync-window-overlay 'sync-window-slave t))
(setq start (line-beginning-position start))
(forward-line (1- p))
(set-window-start (selected-window) start)
(set-window-vscroll (selected-window) vscroll)
(other-window 1)
(unless display-start
(redisplay t))
)))
(defvar sync-window-mode-hook nil
"Hooks to be run at start of `sync-window-mode'.")
(define-minor-mode sync-window-mode
"Synchronized view of two buffers in two side-by-side windows."
:group 'windows
:lighter " ⇕"
(if sync-window-mode
(progn
(add-hook 'post-command-hook 'sync-window-wrapper 'append t)
(add-to-list 'window-scroll-functions 'sync-window-wrapper)
(run-hooks 'sync-window-mode-hook)
(sync-window))
(remove-hook 'post-command-hook 'sync-window-wrapper t)
(setq window-scroll-functions (remove 'sync-window-wrapper window-scroll-functions))
))
(defun sync-window-wrapper (&optional window display-start)
"This wrapper makes sure that `sync-window' is fired from `post-command-hook'
only when the buffer of the active window is in `sync-window-mode'."
(with-selected-window (or window (selected-window))
(when sync-window-mode
(sync-window display-start))))
(provide 'sync-window)

Related

Emacs: How to enable a mode globally?

I just have a mode from an addon which I want to enable globally. In order to turn on it by hand I need to enter M-x highlight-indentation-mode. So, below is a list of what I have tried yet: (highlight-indentation-mode t), (highlight-indentation-mode 1), (setq highlight-indentation-mode t). Nothing worked. Next I figure out that may be I need to enable a mode globally, and I started google about it. What I have tried next:
(define-globalized-minor-mode global-highlight-indentation-mode highlight-indentation-mode
(lambda () (setq highlight-indentation-mode t)))
No, this surely aren't the droids I am looking for, it turns on the variable, but a mode still doesn't work.
(define-globalized-minor-mode global-highlight-indentation-mode highlight-indentation-mode
(lambda () highlight-indentation-mode t))
(define-globalized-minor-mode global-highlight-indentation-mode highlight-indentation-mode
(highlight-indentation-mode t))
These two just broke my Emacs: when I tried open file with this two commands in config, Emacs wrote an error, and refused to open a files.
UPD: Based on comments I also tried
(defun enable-highlight-indentation-mode ()
(interactive)
(highlight-indentation-mode t))
(define-globalized-minor-mode global-highlight-indentation-mode highlight-indentation-mode
enable-highlight-indentation-mode)
(global-highlight-indentation-mode t)
And the same without (interactive). When I am try to open a file with this, Emacs refuse to open, and write an error:
File mode specification error: (void-function nil)
c-font-lock-fontify-region: Symbol's function definition is void: nil
;;; highlight-indentation.el --- Minor modes for highlighting indentation
;; Author: Anton Johansson <anton.johansson#gmail.com> - http://antonj.se
;; Created: Dec 15 23:42:04 2010
;; Version: 0.6.0
;; URL: https://github.com/antonj/Highlight-Indentation-for-Emacs
;;
;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 2 of
;; the License, or (at your option) any later version.
;;
;; This program is distributed in the hope that it will be
;; useful, but WITHOUT ANY WARRANTY; without even the implied
;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
;; PURPOSE. See the GNU General Public License for more details.
;;
;;; Commentary:
;; Customize `highlight-indentation-face', and
;; `highlight-indentation-current-column-face' to suit your theme.
;;; Code:
(defgroup highlight-indentation nil
"Highlight Indentation"
:prefix "highlight-indentation-"
:group 'basic-faces)
(defface highlight-indentation-face
;; Fringe has non intrusive color in most color-themes
'((t :inherit fringe))
"Basic face for highlighting indentation guides."
:group 'highlight-indentation)
(defcustom highlight-indentation-offset 4
"Default indentation offset, used if no other can be found from
major mode. This value is always used by
`highlight-indentation-mode' if set buffer local. Set buffer
local with `highlight-indentation-set-offset'"
:group 'highlight-indentation)
(defvar highlight-indentation-current-regex nil)
;;;###autoload
(define-minor-mode highlight-indentation-mode
"Highlight indentation minor mode highlights indentation based
on spaces"
:lighter " ||"
(when highlight-indentation-current-regex ;; OFF
(font-lock-remove-keywords nil `((,highlight-indentation-current-regex
(1 'highlight-indentation-face)))))
(set (make-local-variable 'highlight-indentation-current-regex) nil)
(when highlight-indentation-mode ;; ON
(when (not (local-variable-p 'highlight-indentation-offset))
(set (make-local-variable 'highlight-indentation-offset)
;; Set indentation offset from highlight-indentation-offset if set, otherwise
;; according to major mode
(cond ((and (eq major-mode 'python-mode) (boundp 'python-indent))
python-indent)
((and (eq major-mode 'python-mode) (boundp 'py-indent-offset))
py-indent-offset)
((and (eq major-mode 'python-mode) (boundp 'python-indent-offset))
python-indent-offset)
((eq major-mode 'ruby-mode)
ruby-indent-level)
((and (eq major-mode 'scala-mode) (boundp 'scala-indent:step))
scala-indent:step)
((and (eq major-mode 'scala-mode) (boundp 'scala-mode-indent:step))
scala-mode-indent:step)
((or (eq major-mode 'scss-mode) (eq major-mode 'css-mode))
css-indent-offset)
((eq major-mode 'nxml-mode)
nxml-child-indent)
((eq major-mode 'coffee-mode)
coffee-tab-width)
((eq major-mode 'js-mode)
js-indent-level)
((eq major-mode 'js2-mode)
js2-basic-offset)
((local-variable-p 'c-basic-offset)
c-basic-offset)
(t
(default-value 'highlight-indentation-offset)))))
(set (make-local-variable 'highlight-indentation-current-regex)
(format "\\( \\) \\{%s\\}" (- highlight-indentation-offset 1)))
(font-lock-add-keywords nil `((,highlight-indentation-current-regex
(1 'highlight-indentation-face)))))
(font-lock-fontify-buffer))
;;;###autoload
(defun highlight-indentation-set-offset (offset)
"Set indentation offset localy in buffer, will prevent
highlight-indentation from trying to guess indentation offset
from major mode"
(interactive
(if (and current-prefix-arg (not (consp current-prefix-arg)))
(list (prefix-numeric-value current-prefix-arg))
(list (read-number "Indentation offset: "))))
(set (make-local-variable 'highlight-indentation-offset) offset)
(when highlight-indentation-mode
(highlight-indentation-mode)))
;;;
;;; Copyright (C) Kresten Krab Thorup
;;; Available under Apache License, Version 2.
;;;
;;; This minor mode will highlight the indentation of the current line
;;; as a vertical bar (grey background color) aligned with the column of the
;;; first character of the current line.
;;;
(defface highlight-indentation-current-column-face
;; Fringe has non intrusive color in most color-themes
'((t :inherit fringe))
"Basic face for highlighting indentation guides."
:group 'highlight-indentation)
;; used to hold the last regex we installed
(defvar highlight-indentation-current-column-regex nil)
;;;###autoload
(define-minor-mode
highlight-indentation-current-column-mode
"Hilight Indentation minor mode displays
a vertical bar corresponding to the indentation of the current line"
:lighter " |"
(when highlight-indentation-current-column-regex
(font-lock-remove-keywords nil highlight-indentation-current-column-regex))
(set (make-local-variable 'highlight-indentation-current-column-regex) nil)
(cond (highlight-indentation-current-column-mode
(add-hook 'post-command-hook 'highlight-indentation-current-column-post-command-hook nil t))
(t
(remove-hook 'post-command-hook 'highlight-indentation-current-column-post-command-hook t)
(font-lock-fontify-buffer))))
(defun highlight-indentation-current-column-post-command-hook ()
"This hook runs after every keystroke"
(when highlight-indentation-current-column-regex
(font-lock-remove-keywords nil highlight-indentation-current-column-regex))
(let ((indent (save-excursion (back-to-indentation) (current-column))))
(when (and highlight-indentation-current-column-mode
(> indent 1))
(let* ((re (format "^ \\{%d\\}\\( \\)" indent))
(arg `((,re (1 'highlight-indentation-current-column-face prepend)))))
(set (make-local-variable 'highlight-indentation-current-column-regex) arg)
(font-lock-add-keywords nil arg))))
(font-lock-fontify-buffer))
(defun turn-on-highlight-indentation-mode ()
(interactive)
(highlight-indentation-mode 1))
(define-globalized-minor-mode global-highlight-indentation-mode
highlight-indentation-mode turn-on-highlight-indentation-mode)
(global-highlight-indentation-mode 1)
(provide 'highlight-indentation)

Sync two windows

I have this code that is "partially" working.
I am trying to sync two windows, so regardless which window you are in the other will sync and start moving accordingly.
The inconsistency I am seeing are around page boundaries; if you move the cursor in one window all the way down till you scroll one more into the next page then directly go up again one line you will notice that both windows will go out of sync. I tried debugging this with no luck. Not sure what is causing this weird behavior.
Here is the code:
(defun Xsync-window (&optional display-start)
"Synchronize point position other window in current frame.
Only works if there are exactly two windows in the active wrame not counting the minibuffer."
(interactive)
(when (= (count-windows 'noMiniBuf) 2)
(let ((p (line-number-at-pos))
(start (line-number-at-pos (or display-start (window-start))))
(vscroll (window-vscroll)))
(other-window 1)
(goto-char (point-min))
(setq start (line-beginning-position start))
(forward-line (1- p))
(set-window-start (selected-window) start)
(set-window-vscroll (selected-window) vscroll)
(other-window 1)
(unless display-start
(redisplay t))
)))
(define-minor-mode sync-window-mode
"Synchronized view of two buffers in two side-by-side windows."
:group 'windows
:lighter " ⇕"
(unless (boundp 'sync-window-mode-active)
(setq sync-window-mode-active nil))
(if sync-window-mode
(progn
(add-hook 'post-command-hook 'sync-window-wrapper 'append t)
(add-to-list 'window-scroll-functions 'sync-window-wrapper)
(Xsync-window)
)
(remove-hook 'post-command-hook 'sync-window-wrapper t)
(setq window-scroll-functions (remove 'sync-window-wrapper window-scroll-functions))
))
(defun sync-window-wrapper (&optional window display-start)
"This wrapper makes sure that `sync-window' is fired from `post-command-hook'
only when the buffer of the active window is in `sync-window-mode'."
(unless sync-window-mode-active
(setq sync-window-mode-active t)
(with-selected-window (or window (selected-window))
(when sync-window-mode
(Xsync-window display-start)))
(setq sync-window-mode-active nil))
)
(defun sync-window-dual ()
"Toggle synchronized view of two buffers in two side-by-side windows simultaneously."
(interactive)
(if (not (= (count-windows 'noMiniBuf) 2))
(error "restricted to two windows")
(let ((mode (if sync-window-mode 0 1)))
(sync-window-mode mode)
(with-selected-window (selected-window)
(other-window 1)
(sync-window-mode mode)))))
When the cursor ends up outside a window, Emacs will reposition the window. However, this occurs after the post-command-hook is called.
If you call (sit-for 0) in your post-command-hook, the window will be redisplayed, and you get the new value for window-start etc.

Sync two windows of emacs together

I have a snippet of code in my dotemacs file that would sync two opened buffers side by side (Thanks to Tobias), scrolling in the master buffer will result in moving the slave buffer accordingly matching the same "line" the cursor is at.
I have been trying to modify the code and have one buffer act as master when it has the focus and the other act as a slave following lead. Basically, I want then both to sync up no matter which buffer is scrolling.
Unfortunately, Applying (Xsync-window) on both buffers failed because of how tightly synced the master and slave together.
Here is the code:
(defun Xsync-window (&optional display-start)
"Synchronize point position other window in current frame.
Only works if there are exactly two windows in the active wrame not counting the minibuffer."
(interactive)
(when (= (count-windows 'noMiniBuf) 2)
(let ((p (line-number-at-pos))
(start (line-number-at-pos (or display-start (window-start))))
(vscroll (window-vscroll)))
(other-window 1)
(goto-char (point-min))
(setq start (line-beginning-position start))
(forward-line (1- p))
(set-window-start (selected-window) start)
(set-window-vscroll (selected-window) vscroll)
(other-window 1)
(unless display-start
(redisplay t))
)))
(define-minor-mode sync-window-mode
"Synchronized view of two buffers in two side-by-side windows."
:group 'windows
:lighter " ⇕"
(if sync-window-mode
(progn
(add-hook 'post-command-hook 'sync-window-wrapper 'append t)
(add-to-list 'window-scroll-functions 'sync-window-wrapper)
(Xsync-window)
)
(remove-hook 'post-command-hook 'sync-window-wrapper t)
(setq window-scroll-functions (remove 'sync-window-wrapper window-scroll-functions))
))
(defun sync-window-wrapper (&optional window display-start)
"This wrapper makes sure that `sync-window' is fired from `post-command-hook'
only when the buffer of the active window is in `sync-window-mode'."
(with-selected-window (or window (selected-window))
(when sync-window-mode
(Xsync-window display-start)
)))
This should do the trick:
(define-minor-mode sync-window-mode
"Synchronized view of two buffers in two side-by-side windows."
:group 'windows
:lighter " ⇕"
(unless (boundp 'sync-window-mode-active)
(setq sync-window-mode-active nil))
(if sync-window-mode
(progn
(add-hook 'post-command-hook 'sync-window-wrapper 'append t)
(add-to-list 'window-scroll-functions 'sync-window-wrapper)
(Xsync-window))
(remove-hook 'post-command-hook 'sync-window-wrapper t)
(setq window-scroll-functions (remove 'sync-window-wrapper window-scroll-functions))))
(defun sync-window-wrapper (&optional window display-start)
"This wrapper makes sure that `sync-window' is fired from `post-command-hook'
only when the buffer of the active window is in `sync-window-mode'."
(unless sync-window-mode-active
(setq sync-window-mode-active t)
(with-selected-window (or window (selected-window))
(when sync-window-mode
(Xsync-window display-start)))
(setq sync-window-mode-active nil)))
This basically guards via sync-window-mode-active, whether Xsync-windows is already working.
You can also toggle the mode in two windows simultaneously with:
(defun sync-window-dual ()
"Toggle synchronized view of two buffers in two side-by-side windows simultaneously."
(interactive)
(if (not (= (count-windows 'noMiniBuf) 2))
(error "restricted to two windows")
(let ((mode (if sync-window-mode 0 1)))
(sync-window-mode mode)
(with-selected-window (selected-window)
(other-window 1)
(sync-window-mode mode)))))

How do I make the compilation window in Emacs to always be a certain size?

I want to make the compilation window in Emacs to always appear at the bottom of a window, and always be a certain height. So far I put the following lines in my .emacs file:
(setq split-height-threshold 0)
(setq compilation-window-height 10)
...and it does work for when I have only one window open, but as soon as I split the screen into two windows horizontally (that is, the dividing line in the middle goes from the top to the bottom), the compilation window stops respecting the height variable, and splits the window right in the middle.
How do I fix this?
I would use something like this, freely adapted from the EmacsWiki:
(defun my-compilation-hook ()
(when (not (get-buffer-window "*compilation*"))
(save-selected-window
(save-excursion
(let* ((w (split-window-vertically))
(h (window-height w)))
(select-window w)
(switch-to-buffer "*compilation*")
(shrink-window (- h compilation-window-height)))))))
(add-hook 'compilation-mode-hook 'my-compilation-hook)
If the *compilation* buffer is not visible, this will split the window vertically, resize the newly opened window to 10 lines height, and open the *compilation* buffer in it.
You can customize the variable compilation-window-height.
Combining code from How can I prevent emacs from opening new window for compilation output? and code from http://www.emacswiki.org/emacs/CompilationMode, this is all my code for compile, it provides you 4 features:
1). Use compile-again to run the same compile as the last time automatically, no prompt. If there is no last time, or there is a prefix argument, it acts like M-x compile.
2). compile will split the current window(always be a certain size), it will not affect the other windows in this frame.
3). it will auto-close the *compilation* buffer (window) if there is no error, keep it if error exists.
4). it will highlight the error line and line number of the source code in the *compilation* buffer, use M-n/p to navigate every error in *compilation* buffer, Enter in the error line to jump to the line in your code code.
(require 'compile)
(setq compilation-last-buffer nil)
(defun compile-again (ARG)
"Run the same compile as the last time.
If there is no last time, or there is a prefix argument, this acts like M-x compile."
(interactive "p")
(if (and (eq ARG 1)
compilation-last-buffer)
(progn
(set-buffer compilation-last-buffer)
(revert-buffer t t))
(progn
(call-interactively 'compile)
(setq cur (selected-window))
(setq w (get-buffer-window "*compilation*"))
(select-window w)
(setq h (window-height w))
(shrink-window (- h 10))
(select-window cur))))
(global-set-key (kbd "C-x C-m") 'compile-again)
(defun my-compilation-hook ()
"Make sure that the compile window is splitting vertically."
(progn
(if (not (get-buffer-window "*compilation*"))
(progn
(split-window-vertically)))))
(add-hook 'compilation-mode-hook 'my-compilation-hook)
(defun compilation-exit-autoclose (STATUS code msg)
"Close the compilation window if there was no error at all."
;; If M-x compile exists with a 0
(when (and (eq STATUS 'exit) (zerop code))
;; then bury the *compilation* buffer, so that C-x b doesn't go there
(bury-buffer)
;; and delete the *compilation* window
(delete-window (get-buffer-window (get-buffer "*compilation*"))))
;; Always return the anticipated result of compilation-exit-message-function
(cons msg code))
(setq compilation-exit-message-function 'compilation-exit-autoclose)
(defvar all-overlays ())
(defun delete-this-overlay(overlay is-after begin end &optional len)
(delete-overlay overlay)
)
(defun highlight-current-line ()
"Highlight current line."
(interactive)
(setq current-point (point))
(beginning-of-line)
(setq beg (point))
(forward-line 1)
(setq end (point))
;; Create and place the overlay
(setq error-line-overlay (make-overlay 1 1))
;; Append to list of all overlays
(setq all-overlays (cons error-line-overlay all-overlays))
(overlay-put error-line-overlay
'face '(background-color . "red"))
(overlay-put error-line-overlay
'modification-hooks (list 'delete-this-overlay))
(move-overlay error-line-overlay beg end)
(goto-char current-point))
(defun delete-all-overlays ()
"Delete all overlays"
(while all-overlays
(delete-overlay (car all-overlays))
(setq all-overlays (cdr all-overlays))))
(defun highlight-error-lines(compilation-buffer process-result)
(interactive)
(delete-all-overlays)
(condition-case nil
(while t
(next-error)
(highlight-current-line))
(error nil)))
(setq compilation-finish-functions 'highlight-error-lines)
There's an excellent package for these situations named Shackle. https://github.com/wasamasa/shackle
Easy to set up and works on pretty much any type of buffer

How to execute emacs grep-find link in the same window?

When I use grep-find it opens another window (area in the frame) with a list of results that I can select. When I select one it opens the target file in a different window than grep-find is in.
How can I get the target file to open in the same window as the grep results (replacing the grep results window with what I am actually looking for).
How can I keep grep-find from opening a separate window (have it so it opens in the current window). My goal is I look for something, I find it, I go to it, all within the same window. I would like to add this to my .emacs file.
It doesn't look like there is any way to configure the compile package to do what you're asking. And there's no easy way to use advice to tweak the behavior. I think you have to resort to editing the function which actually jumps to the error, which you can do with the following addition to your .emacs (tested in 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)))))))
The eval-afer-load portion just ensures that you re-define it after Emacs defined it, so that your change takes hold.
You can add a binding (e.g. Alt-m) and do the following
(define-key grep-mode-map "\M-m" (lambda()
(interactive)
(compile-goto-error)
(delete-other-windows)
(kill-buffer "*grep*")))
I didn't find a way to replace the standard "Enter" / Mouse-click binding with a custom function
There is an another approach:
(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))
I had the same question, and found this answer over at 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)
Pressing o in the *grep* buffer will open the location and file in the same frame.
I found this an elegant solution without deleting frames or too much lisp code and just hooking into compilation-mode-hook.