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

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.

Related

emacs - scroll past top of buffer?

Emacs (and all other text editors) by default show blank space below the bottom lines of a buffer. I want emacs to be able to also scroll above/show blank space like this above the top lines in a buffer as well so that the top lines can be viewed in the center of the screen for small files.
With guidance from Thomas's answer here I have created a minor mode for this which is now available on MELPA:
TopSpace - Recenter line 1 with scrollable upper margin/padding
I've started a small minor-mode to accomplish this. However, as first versions go, it's probably buggy, doesn't handle all edge cases (such as e.g., narrowing), and isn't particularly efficient.
Thus, I'd be happy to accept improvements: feel free to directly edit this answer if you can make this code better or to extend it.
(defvar vertical-center-num-buffers 0
"The number of buffers in which `vertical-center-mode' is activated.")
(define-minor-mode vertical-center-mode
"This minor mode displays the contents of a buffer vertically
centered with respect to the window height. This, of course, only
makes sense for buffers whose content is shorter than the window
height."
nil
" vc"
nil
;; is the mode being turned on or off?
(if vertical-center-mode
;; on
(progn
;; keep track of the number of lines in the buffer
(setq-local vertical-center-num-lines (count-lines (point-min) (point-max)))
;; use an overlay to display empty lines at the beginning of the buffer
(setq-local vertical-center-overlay (make-overlay (point-min) (point-max)))
;; initial call to the function that centers the buffer contents
(vertical-center--lines-changed 0)
;; react to changes to the buffer or the window
(add-hook 'kill-buffer-hook 'vertical-center--kill-buffer)
(add-hook 'window-size-change-functions 'vertical-center--window-size-changed)
(when (= vertical-center-num-buffers 0)
(add-hook 'before-change-functions 'vertical-center--before-change)
(add-hook 'after-change-functions 'vertical-center--after-change))
;; this is just to play nice and remove the above hook
;; functions when they're no longer needed. Let's keep our
;; fingers crossed that we'll always stay in sync.
(setq vertical-center-num-buffers (1+ vertical-center-num-buffers)))
;; off
;; delete/unset data structures when the mode is turned off
(delete-overlay vertical-center-overlay)
(makunbound 'vertical-center-num-lines)
(makunbound 'vertical-center-overlay)
(setq vertical-center-num-buffers (1- vertical-center-num-buffers))
;; remove hook functions when they're no longer needed
(when (= vertical-center-num-buffers 0)
(remove-hook 'kill-buffer-hook 'vertical-center--kill-buffer)
(remove-hook 'window-size-change-functions 'vertical-center--window-size-changed)
(remove-hook 'before-change-functions 'vertical-center--before-change)
(remove-hook 'after-change-functions 'vertical-center--after-change))))
;; handle killing of buffers
(defun vertical-center--kill-buffer ()
(when vertical-center-mode
(setq vertical-center-num-buffers (1- vertical-center-num-buffers))))
;; react to changes in the window height
(defun vertical-center--window-size-changed (arg)
(vertical-center--lines-changed 0))
;; handle deletions of buffer text
(defun vertical-center--before-change (beginning end)
(when (boundp 'vertical-center-num-lines)
(let ((num-lines 0))
(while (< beginning end)
(when (= (char-after beginning) ?\n)
(setq num-lines (1- num-lines)))
(setq beginning (1+ beginning)))
(when (< num-lines 0)
(vertical-center--lines-changed num-lines)))))
;; handle insertions into the buffer
(defun vertical-center--after-change (beginning end previous-length)
(when (boundp 'vertical-center-num-lines)
(let ((num-lines 0))
(while (< beginning end)
(when (= (char-after beginning) ?\n)
(setq num-lines (1+ num-lines)))
(setq beginning (1+ beginning)))
(when (> num-lines 0)
(vertical-center--lines-changed num-lines)))))
;; update the display when either the buffer content or the window
;; height has changed
(defun vertical-center--lines-changed (num-lines)
(setq vertical-center-num-lines (+ vertical-center-num-lines num-lines))
(let ((top-margin (/ (- (window-height) vertical-center-num-lines) 2)))
;; set the top margin
(overlay-put vertical-center-overlay 'before-string
(when (> top-margin 0)
(make-string top-margin ?\n)))))
Save the above code in a file named "vertical-center.el" in a directory of your choice, and then add the following lines to your .emacs file:
(setq load-path (append load-path "<directory>"))
(autoload 'vertical-center-mode "vertical-center")
Here, <directory> should be the path to the directory in which you saved the "vertical-center.el" file.
After restarting Emacs, you can now activate or deactivate the mode by typing M-x vertical-center-mode.

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.

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

Emacs - set mark on edit location

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)