Emacs - set mark on edit location - emacs

I want emacs to add last edit location to the mark ring, so I can jump back to previous edit locations.
Ideally this would only mark one edit location per line. When I edit another line, the last edit location on that line would be added to the ring, and so forth.
I'm not familiar with Lisp to implement this myself. If anyone knows of a plugin or can kindly provide a solution that would be great! :)

You can install a package goto-last-change which allows you to jump sequentially to the buffer undo positions (last edit locations).

Session.el provides this functionality bound to "C-x C-/" or session-jump-to-last-change.
Session dos it per buffer. I'm unaware of anything that does it globally.

I implement a similar function, by recording 2 file's last edit locations(not per buffer), and cycle them when requested. Somewhat like how eclipse does(but less powerful, only 2 file's are recorded)
emacs-last-edit-location
the code:
;;; record two different file's last change. cycle them
(defvar feng-last-change-pos1 nil)
(defvar feng-last-change-pos2 nil)
(defun feng-swap-last-changes ()
(when feng-last-change-pos2
(let ((tmp feng-last-change-pos2))
(setf feng-last-change-pos2 feng-last-change-pos1
feng-last-change-pos1 tmp))))
(defun feng-goto-last-change ()
(interactive)
(when feng-last-change-pos1
(let* ((buffer (find-file-noselect (car feng-last-change-pos1)))
(win (get-buffer-window buffer)))
(if win
(select-window win)
(switch-to-buffer-other-window buffer))
(goto-char (cdr feng-last-change-pos1))
(feng-swap-last-changes))))
(defun feng-buffer-change-hook (beg end len)
(let ((bfn (buffer-file-name))
(file (car feng-last-change-pos1)))
(when bfn
(if (or (not file) (equal bfn file)) ;; change the same file
(setq feng-last-change-pos1 (cons bfn end))
(progn (setq feng-last-change-pos2 (cons bfn end))
(feng-swap-last-changes))))))
(add-hook 'after-change-functions 'feng-buffer-change-hook)
;;; just quick to reach
(global-set-key (kbd "M-`") 'feng-goto-last-change)

Related

on Emacs for OSX, how to keep kill ring and clipboard separate?

In GNU Emacs for OSX, how can I keep the kill ring and OSX clipboard separate? (Such that I essentially have two separate kill rings.)
With desired behavior, this would work:
1. ⌘C to copy text from the web to OSX clipboard.
2. controlk to kill a line in Emacs.
3. controly to yank killed text from Emacs kill ring to current Emacs buffer.
4. ⌘v to paste original web text from OSX clipboard to current Emacs buffer.
This works out of the box in Aquamacs. How to make work in GNU Emacs?
This question was discussed as it pertains to Windows here:
Emacs: How to separate the kill ring from the system clipboard?
and here:
http://lists.gnu.org/archive/html/help-emacs-windows/2010-02/msg00001.HTML
...but this solution does not work in OSX. I would like a solution for Mac OSX.
The solution in Emacs: How to separate the kill ring from the system clipboard? does work, though not complete. You may call pbcopy yourself to get clipboard pasting right. For instance, try the following in your .emacs. Note that s-v is for Cmd+V in an OS X window system. Same goes for s-c.
;;; Tested on:
;;; 1. GNU Emacs 24.3.1 (x86_64-apple-darwin13.0.0)
;;; of 2013-12-22 on tennine-slave.macports.org
;;; (MacPorts emacs#24.3_1)
;;;
;;; 2. GNU Emacs 24.3.1 (x86_64-apple-darwin, NS apple-appkit-1038.36)
;;; of 2013-03-12 on bob.porkrind.org
;;; (Emacs For Mac OS X)
(defun isolate-kill-ring()
"Isolate Emacs kill ring from OS X system pasteboard.
This function is only necessary in window system."
(interactive)
(setq interprogram-cut-function nil)
(setq interprogram-paste-function nil))
(defun pasteboard-copy()
"Copy region to OS X system pasteboard."
(interactive)
(shell-command-on-region
(region-beginning) (region-end) "pbcopy"))
(defun pasteboard-paste()
"Paste from OS X system pasteboard via `pbpaste' to point."
(interactive)
(shell-command-on-region
(point) (if mark-active (mark) (point)) "pbpaste" nil t))
(defun pasteboard-cut()
"Cut region and put on OS X system pasteboard."
(interactive)
(pasteboard-copy)
(delete-region (region-beginning) (region-end)))
(if window-system
(progn
(isolate-kill-ring)
;; bind CMD+C to pasteboard-copy
(global-set-key (kbd "s-c") 'pasteboard-copy)
;; bind CMD+V to pasteboard-paste
(global-set-key (kbd "s-v") 'pasteboard-paste)
;; bind CMD+X to pasteboard-cut
(global-set-key (kbd "s-x") 'pasteboard-cut))
;; you might also want to assign some keybindings for non-window
;; system usage (i.e., in your text terminal, where the
;; command->super does not work)
)
If you ever run into problems with UTF-8, consider the following possible solution:
;; handle emacs utf-8 input
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(prefer-coding-system 'utf-8)
(setenv "LANG" "en_US.UTF-8")
After much fiddling around, I'm pretty sure that the only way to make this work is to override the x-select-text method. Check out my answer here for all the details: https://stackoverflow.com/a/23254771/71522
NOTE:  This draft solution is not meant to be an Emacs system-wide modification separating the clipboards -- instead, this is a custom solution designed to keep the clipboards separated on an interactive basis only when specifically using these custom functions. Other functions within
Emacs that use the kill-ring can be modified using a similar method -- the variables interprogram-cut-function and interprogram-paste-function can be made let-bound to a nil value for the duration of the specific functions (either through advice, or modification of the source itself, or creating new functions and/or using a defalias). However, the latter is beyond the scope of this limited example.
HISTORY
First Draft (December 23, 2014):  This is a first draft, which is based on the idea that the OSX clipboard may be accessed only when using C-u before calling either the copy or paste functions. If C-u is called first, then the OSX clipboard is utilized. As I use the functions more on a daily basis, I may have additional revisions to this code and I will update same from time to time:
EDIT (December 24, 2014):  Removed * from the interactive command statement as to lawlist-copy-selected-region -- that was a read-only check needed for pasting, but not copying. Added a statement regarding the general nature of this example.
EDIT (December 28, 2014):  Revised code to better handle when the user forgot to select a region before calling lawlist-copy-selected-region. Small revisions to make the code more concise.
(defun lawlist-copy-selected-region (&optional arg)
(interactive "P")
(let* (
(interprogram-cut-function
(when (equal arg '(4)) interprogram-cut-function))
(interprogram-paste-function
(when (equal arg '(4)) interprogram-paste-function))
(region-active-p (region-active-p))
(beg (when region-active-p (region-beginning)))
(end (when region-active-p (region-end)))
(copied-string
(when region-active-p (buffer-substring-no-properties beg end))) )
(unless region-active-p
(let ((debug-on-quit nil))
(signal 'quit `("No region has been selected!"))))
(copy-region-as-kill beg end)
(when (not (active-minibuffer-window))
(message "%s"
(concat
(if (and interprogram-cut-function interprogram-paste-function)
"OSX+Emacs: "
"Emacs: ")
(truncate-string-to-width copied-string 40)
(when (> (length copied-string) 40)
" . . .")))) ))
(defun lawlist-yank (&optional arg)
(interactive "*P")
(unless arg (setq arg 1))
(setq yank-window-start (window-start))
(setq this-command t)
(push-mark (point))
(insert-for-yank
(lawlist-current-kill
(cond
((listp arg)
arg)
((eq arg '-)
-2)
(t
(1- arg) ))))
(if (consp arg)
(goto-char (prog1 (mark t)
(set-marker (mark-marker) (point) (current-buffer)))))
(if (eq this-command t)
(setq this-command 'yank))
(when (region-active-p)
(setq mark-active nil))
nil)
(defun lawlist-current-kill (n &optional do-not-move)
(let ((interprogram-paste
(and
(equal n '(4))
interprogram-paste-function
(funcall interprogram-paste-function))))
(cond
(interprogram-paste
(let ((interprogram-cut-function nil))
(if (listp interprogram-paste)
(mapc 'kill-new (nreverse interprogram-paste))
(kill-new interprogram-paste)))
(car kill-ring))
((and (equal n '(4)) (not interprogram-paste))
(car kill-ring))
(t
(or kill-ring
(let ((debug-on-quit nil))
(signal 'quit `("The kill-ring is empty."))))
(let (
(ARGth-kill-element
(nthcdr
(mod (- n (length kill-ring-yank-pointer)) (length kill-ring))
kill-ring)))
(unless do-not-move
(setq kill-ring-yank-pointer ARGth-kill-element)
(when
(and
yank-pop-change-selection
(> n 0)
interprogram-cut-function)
(funcall interprogram-cut-function (car ARGth-kill-element))))
(car ARGth-kill-element))))))
(global-set-key (kbd "C-x M-y")
(lambda ()
(interactive)
(insert-string (ns-get-pasteboard))))
(global-set-key (kbd "C-x M-w")
(lambda ()
(interactive)
(when (region-active-p)
(ns-set-pasteboard
(buffer-substring (region-beginning)
(region-end))))))
simpleclip might be helpful -
Simplified access to the system clipboard in Emacs.
simpleclip-mode radically simplifies clipboard handling: the system
clipboard and the Emacs kill ring are made completely independent, and
never influence each other.
The super keybindings are friendly for OS X: super is generally mapped
to the "command" key ie ⌘.
Tested on OS X, X11, and MS Windows
https://github.com/rolandwalker/simpleclip
Use
(setq select-enable-clipboard nil)
This will only separate the two clipboards, and for ⌘ c and ⌘ v to work like mentioned you will have to rebind them to clipboard-kill-ring-save and clipboard-yank:
(keymap-global-set "s-c" 'clipboard-kill-ring-save)
(keymap-global-set "s-x" 'clipboard-kill-region)
(keymap-global-set "s-v" 'clipboard-yank)
I am using this Emacs: https://github.com/railwaycat/emacs-mac-port, and it also works on Emacs 28 built from source.

Is there emacs capability for visiting last edits?

In the JetBrains products, there's a very handy key binding that lets you visit all the spots you made an edit. Hit the key once to go to the last edit (file and location), and keep hitting the key to go back to earlier edits. It's typically when editing that you want to be editing the same places over and over again, and if one has many buffers open, many of which are not edited, this is even more useful.
Emacs has a mark ring, but that's not quite the same thing.
On a related note, is there functionality in magit, the emacs git add-on, to jump to edits?
There is GotoLastChange which allows you to travel along the chain of undo locations. You can assign it to a key:
(global-set-key "\C-x\C-\\" 'goto-last-change)
There is GotoChg which allows you to travel back and forth the chain of undo locations. Sample init code snippet:
(require 'goto-chg)
(global-set-key [(control ?.)] 'goto-last-change)
(global-set-key [(control ?,)] 'goto-last-change-reverse)
(Just like the other alternatives, GotoLastChange and session.el, it can not jump between buffers)
Global, multi-buffer goto-last-change:
;;; record two different file's last change. cycle them
(defvar feng-last-change-pos1 nil)
(defvar feng-last-change-pos2 nil)
(defun feng-swap-last-changes ()
(when feng-last-change-pos2
(let ((tmp feng-last-change-pos2))
(setf feng-last-change-pos2 feng-last-change-pos1
feng-last-change-pos1 tmp))))
(defun feng-goto-last-change ()
(interactive)
(when feng-last-change-pos1
(let* ((buffer (find-file-noselect (car feng-last-change-pos1)))
(win (get-buffer-window buffer)))
(if win
(select-window win)
(switch-to-buffer-other-window buffer))
(goto-char (cdr feng-last-change-pos1))
(feng-swap-last-changes))))
(defun feng-buffer-change-hook (beg end len)
(let ((bfn (buffer-file-name))
(file (car feng-last-change-pos1)))
(when bfn
(if (or (not file) (equal bfn file)) ;; change the same file
(setq feng-last-change-pos1 (cons bfn end))
(progn (setq feng-last-change-pos2 (cons bfn end))
(feng-swap-last-changes))))))
(add-hook 'after-change-functions 'feng-buffer-change-hook)
;;; just quick to reach
(global-set-key (kbd "M-`") 'feng-goto-last-change)
from http://shenfeng.me/emacs-last-edit-location.html
This implementation works for the last two changes in any buffers. I imagine extending the length of its change-list beyond two wouldn't be too hard.
There is the command session-jump-to-last-change in session.el which allows you to travel along the chain of undo locations. Init code snippet:
(require 'session)
(setq session-jump-undo-threshold 80) ; default was 240
(global-set-key [(control ?.)] 'session-jump-to-last-change)
(Just like the other alternatives, GotoLastChange and GotoChg, it can not jump between buffers)
Single buffer
Tracking edits and go back to where they occurred depends on the type of them.
If your edit added something, you can go back to it with a rather simple:
(goto-char (car(cadr buffer-undo-list)))
If you deleted, something you can go back to it with:
(goto-char (abs (cdr(cadr buffer-undo-list))))
and you might like displaying what you deleted in the minibuffer:
(progn
(goto-char (abs (cdr(cadr buffer-undo-list))))
(message "DEL->: %s" (substring-no-properties (car(cadr buffer-undo-list)))))
Summing up:
(defun last-edit ()
"Go back to last add/delete edit"
(interactive)
(let* ((ubuf (cadr buffer-undo-list))
(beg (car ubuf))
(end (cdr ubuf)))
(cond
((integerp beg) (goto-char beg))
((stringp beg) (goto-char (abs end))
(message "DEL-> %s" (substring-no-properties beg)))
(t (message "No add/delete edit occurred")))))
Read C-h v buffer-undo-list and you might integrate this for less subtle edits, such as setting text properties (assuming you really need it).
Multi-buffer
I used the buffer-undo-list variable to carry out the tasks. There is a distinct list for each buffer and, as far as I know, there is no global undo-list. Most likely you know in which buffer you typed something and you want Emacs to bring to the edited spot. There is in this case a single global-mark-ring variable recording the sequence of buffers that you have been.
Successive uses of the command Meta-Xpop-global-mark,
or simply
Ctrl-X Ctrl-Space,
will bring you to earlier visited buffers (and mark positions). Once you get to the target buffer, you can trigger Meta-Xlast-edit (or the bound keys).

Emacs and ansi-term: Elisp iterate through a list of buffers

I'm using the following code, to open ansi-term. I found this here.
(require 'term)
(defun visit-ansi-term ()
"If the current buffer is:
1) a running ansi-term named *ansi-term*, rename it.
2) a stopped ansi-term, kill it and create a new one.
3) a non ansi-term, go to an already running ansi-term
or start a new one while killing a defunt one"
(interactive)
(let ((is-term (string= "term-mode" major-mode))
(is-running (term-check-proc (buffer-name)))
(term-cmd "/usr/local/bin/bash")
(anon-term (get-buffer "*ansi-term*")))
(if is-term
(if is-running
(if (string= "*ansi-term*" (buffer-name))
(call-interactively 'rename-buffer)
(if anon-term
(switch-to-buffer "*ansi-term*")
(ansi-term term-cmd)))
(kill-buffer (buffer-name))
(ansi-term term-cmd))
(if anon-term
(if (term-check-proc "*ansi-term*")
(switch-to-buffer "*ansi-term*")
(kill-buffer "*ansi-term*")
(ansi-term term-cmd))
(ansi-term term-cmd)))))
(global-set-key (kbd "<f2>") 'visit-ansi-term)
Now I want to modify this, such that after renaming a buffer it remembers its name and when I use a keyboard shortcut to iterate through the renamed buffers list.
so if I press [F2] and it finds that ansi-term is running, it asks me if I want to rename it. I rename it to say, BUILD. I would like a function and bind to Say [F3] to iterate thorough the list of ansi-terms opened.
I'm a ELISP illiterate. would be glad it someone pointed be references which might help me doing this.
Thanks.
The following code/binding cycles through all the buffers whose major mode is term-mode:
(global-set-key (kbd "<f3>") 'cycle-ansi-term)
(defun cycle-ansi-term ()
"cycle through buffers whose major mode is term-mode"
(interactive)
(when (string= "term-mode" major-mode)
(bury-buffer))
(let ((buffers (cdr (buffer-list))))
(while buffers
(when (with-current-buffer (car buffers) (string= "term-mode" major-mode))
(switch-to-buffer (car buffers))
(setq buffers nil))
(setq buffers (cdr buffers)))))

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.