How to automatically save files on lose focus in Emacs - emacs

Is it possible to configure Emacs, so that it saves all files when the emacs window loses
focus?

I added focus hooks to Gnu Emacs 24.4.
They are called focus-in-hook and focus-out-hook.
You can add
(defun save-all ()
(interactive)
(save-some-buffers t))
(add-hook 'focus-out-hook 'save-all)
to your .emacs file and it should save all files on loss of focus.

I use this, it will only work if emacs is running under X (like it probably would in something like ubuntu).
(when
(and (featurep 'x) window-system)
(defvar on-blur--saved-window-id 0 "Last known focused window.")
(defvar on-blur--timer nil "Timer refreshing known focused window.")
(defun on-blur--refresh ()
"Runs on-blur-hook if emacs has lost focus."
(let* ((active-window (x-window-property
"_NET_ACTIVE_WINDOW" nil "WINDOW" 0 nil t))
(active-window-id (if (numberp active-window)
active-window
(string-to-number
(format "%x00%x"
(car active-window)
(cdr active-window)) 16)))
(emacs-window-id (string-to-number
(frame-parameter nil 'outer-window-id))))
(when (and
(= emacs-window-id on-blur--saved-window-id)
(not (= active-window-id on-blur--saved-window-id)))
(run-hooks 'on-blur-hook))
(setq on-blur--saved-window-id active-window-id)
(run-with-timer 1 nil 'on-blur--refresh)))
(add-hook 'on-blur-hook #'(lambda () (save-some-buffers t)))
(on-blur--refresh))

Not sure if this is what you want.
(defun dld-deselect-frame-hook ()
(save-some-buffers 1))
(add-hook 'deselect-frame-hook 'dld-deselect-frame-hook)
From: http://www.dribin.org/dave/blog/archives/2003/09/10/emacs/
EDIT: It only seems to work in XEmacs

[…] the feature I am talking about is from
Scribes. It is very convient when
editing html and the like, you don't
have to press C-x C-s anymore, you
just change the window and check your
browser.
In that case, instead of switching to the browser application, order Emacs to load the browser application (C-c C-v or M-x browse-url-of-buffer). With this method, you can write your own function that saves the buffer and then brings the browser up, like:
(defun my-browse-url-of-buffer ()
"Save current buffer and view its content in browser."
(interactive)
(save-buffer)
(browse-url-of-buffer))
And hook it to a convenient binding.
Or you can still use the html-autoview-mode that each time you saves the buffer, automatically loads the file into your favorite browser.

You can use `auto-save-interval' to save every n characters you type. Mine is set to 100. So about every 2-3 lines of code, maybe?
auto-save-interval is a variable
defined in `C source code'. Its value
is 100
Documentation:
*Number of input events between auto-saves. Zero means disable
autosaving due to number of characters
typed.
You can customize this variable.
This doesn't answer your original question; it's just a way to achieve something similar.

Related

Emacs: fix 'changed on disk'/'Reread from disk' when file has not changed [duplicate]

How to disable Emacs from checking the buffer file was changed outside the editor?
Emacs is really trying to help you here. Read the info page on Protection against Simultaneous Editing.
But, if you still want to avoid that message/prompt, you can redefine the function that is doing the prompting:
(defun ask-user-about-supersession-threat (fn)
"blatantly ignore files that changed on disk"
)
(defun ask-user-about-lock (file opponent)
"always grab lock"
t)
The second function there is for when two people are using Emacs to edit the same file, and would provide a similar prompt (but not the one you seemed to refer to in the question).
I'd advise against overriding the two routines, but it's there if you want.
On the off chance global-auto-revert-mode is on, you could disable that. Add this to your .emacs:
(global-auto-revert-mode -1)
You can tell if the mode is on by looking at the variable of the same name:
C-h v global-auto-revert-mode RET
If the value is t, then the mode is on, otherwise it is off.
I have the following in my .emacs. It makes Emacs only ask about really changed files. If a file remains the same bytewise, just its timestamp is updated, as often happens when you switch branches in VCS, this "change" is ignored by Emacs.
;; Ignore modification-time-only changes in files, i.e. ones that
;; don't really change the contents. This happens often with
;; switching between different VC buffers.
(defun update-buffer-modtime-if-byte-identical ()
(let* ((size (buffer-size))
(byte-size (position-bytes size))
(filename buffer-file-name))
(when (and byte-size (<= size 1000000))
(let* ((attributes (file-attributes filename))
(file-size (nth 7 attributes)))
(when (and file-size
(= file-size byte-size)
(string= (buffer-substring-no-properties 1 (1+ size))
(with-temp-buffer
(insert-file-contents filename)
(buffer-string))))
(set-visited-file-modtime (nth 5 attributes))
t)))))
(defun verify-visited-file-modtime--ignore-byte-identical (original &optional buffer)
(or (funcall original buffer)
(with-current-buffer buffer
(update-buffer-modtime-if-byte-identical))))
(advice-add 'verify-visited-file-modtime :around #'verify-visited-file-modtime--ignore-byte-identical)
(defun ask-user-about-supersession-threat--ignore-byte-identical (original &rest arguments)
(unless (update-buffer-modtime-if-byte-identical)
(apply original arguments)))
(advice-add 'ask-user-about-supersession-threat :around #'ask-user-about-supersession-threat--ignore-byte-identical)
In my case I wanted:
(setq revert-without-query '(".*"))
Documentation for revert-without-query:
Specify which files should be reverted without query.
The value is a list of regular expressions.
If the file name matches one of these regular expressions,
then ‘revert-buffer’ reverts the file without querying
if the file has changed on disk and you have not edited the buffer.
I had annoyance with this because every time I switched branches in git, emacs thought all my files had changed.
Revbuffs helps you cope with the symptoms of this. It allows you to cause all your buffers to be reloaded.
You can also try (global-auto-revert-mode) which will automatically revert your files to what's on disk.

How can one quickly browse through lots of files in Emacs?

is there a way to quickly browse through lots of files in Emacs (24.3)? More specifically:
Let's assume an Emacs frame is split into two windows. Suppose focus is in the left window that has an open 'dired' buffer with lots of text files (or code). I would like to go up and down the list of files (e.g. with cursor keys), while at the same time the current file is shown in the right window. Even better the file is only viewed and closed once I move in the dired buffer to the next file. This would be very useful especially together with some 'omit' mode.
Can this be done in 'dired'? I also coudn't find this functionality in dired-x or in sunrise-commander. Is it possible?
The best candidates I tried already (and why they not solve the problem):
'v' which shows the current file, but also moves the attention
'C-o' which shows the current file, but after moving up or down, I have to press C-o again, also it generates lots of buffers
Thanks a lot for your help!
A simple and generic (while not optimum) solution could be via the C-x () mechanism.
First open the two panes in Emacs, with - say - top one being dired.
Press o to open the first file in the 2nd pane.
Then you can start the repetition mechanism:
do C-x ( to start recording a macro
do C-x k and return to close the buffer
do o again to go back to dired
do down key to go to next file
do o to open next file in bottom pane
do C-x ) to end the macro
From that point (being in bottom pane, dired in top pane), doing a mere
C-x e (and then only e if there is no other operation in between)
will automatically
close bottom pane file, go to top pane, down to next file, open it in bottom pane
There is maybe a more specific way to do that, but knowing the macro mechanism is anyway very helpful in Emacs.
Here's how I do this with view-mode:
(add-hook 'view-mode-hook
(lambda()
(define-key view-mode-map (kbd "n") 'dired-view-next)
(define-key view-mode-map (kbd "p") 'dired-view-prev)))
(defun dired-view-next ()
"Move to next dired line and view ."
(interactive)
(quit-window)
(dired-next-line 1)
(dired-view-file))
(defun dired-view-prev ()
"Move to next dired line and view ."
(interactive)
(quit-window)
(dired-next-line -1)
(dired-view-file))
UPD:
This one has two panes:
(defun dired-view-next-pane ()
(interactive)
(other-window 1)
(if view-mode
(kill-buffer))
(other-window -1)
(dired-next-line 1)
(view-file-other-window
(dired-get-file-for-visit))
(other-window -1))
Thanks a lot for all those answers. Summarizing I created the following solution (extending the answer of "abo-abo"):
;; little modification to dired-mode that let's you browse through lots of files
(add-hook 'dired-mode-hook
(lambda()
(define-key dired-mode-map (kbd "C-o") 'dired-view-current) ; was dired-display-file
(define-key dired-mode-map (kbd "n") 'dired-view-next) ; was dired-next-line
(define-key dired-mode-map (kbd "p") 'dired-view-previous))) ; was dired-previous-line
(defun dired-view-next ()
"Move down one line and view the current file in another window."
(interactive)
(dired-next-line)
(dired-view-current))
(defun dired-view-previous ()
"Move up one line and view the current file in another window."
(interactive)
(dired-previous-line)
(dired-view-current))
(defun dired-view-current ()
"View the current file in another window (possibly newly created)."
(interactive)
(if (not (window-parent))
(split-window)) ; create a new window if necessary
(let ((file (dired-get-file-for-visit))
(dbuffer (current-buffer)))
(other-window 1) ; switch to the other window
(unless (equal dbuffer (current-buffer)) ; don't kill the dired buffer
(if (or view-mode (equal major-mode 'dired-mode)) ; only if in view- or dired-mode
(kill-buffer))) ; ... kill it
(let ((filebuffer (get-file-buffer file)))
(if filebuffer ; does a buffer already look at the file
(switch-to-buffer filebuffer) ; simply switch
(view-file file)) ; ... view it
(other-window -1)))) ; give the attention back to the dired buffer
Three keys are changed:
C-o to view the current item in another window (possibly create one).
n to view the next item in another window.
p to view the previous item in another window.
This can be used in a dired buffer. Note that only dired-mode buffers and view-mode buffers get killed while moving up and down. If a file is shown that another buffer is already visiting (not in view-mode), that buffer is shown as well, but not killed when moving to the next. Another subtlety is the case when the passively shown buffer is the dired buffer used for going through the list (this can easily happen, when going inside a folder with RET). To handle this case, we first check whether we are trying to kill the initial dired buffer.
Load Icicles.
Define this command:
(defun my-find-file ()
"Like `icicle-find-file', but alt action views file temporarily.
Alternate action keys such as `C-S-down' visit the candidate file in
`view-mode' and kill the buffer of the last such viewed candidate."
(interactive)
(let ((icicle-candidate-alt-action-fn
(lambda (file)
(when (and my-last-viewed
(get-file-buffer my-last-viewed))
(kill-buffer (get-file-buffer my-last-viewed)))
(setq my-last-viewed (abbreviate-file-name file))
(view-file file)
(select-frame-set-input-focus
(window-frame (active-minibuffer-window))))))
(icicle-find-file-of-content)))
(defvar my-last-viewed nil
"Last file viewed by alternate action of `my-find-file'.")
Then you can:
Use M-x my-find-file (or bind it to a key - e.g., C-x C-f).
Optionally type part of a file name, to limit the matching names.
Optionally use down or up to cycle among file names.
Use C-S-down to visit the next file in order.
Repeat #4 to see other files in order.
Repeat #2 or #3 to see other sets of files.
End with RET to choose a file to visit or C-g to cancel.
Each file buffer you visited with C-S-down was killed when you
viewed the next one. You can also mix in C-down or C-RET to
also visit files whose buffers you do not want to kill
automatically. (Change view-file to find-file if you don't
want to visit in view-mode, which is read-only.)
[By default, the alternate action for icicle-find-file is
icicle-alt-act-fn-for-type, which prompts you for a file-
appropriate action to use on the particular candidate chosen for
the action. Command my-find-file just substitutes a different
alternate action function (for all candidates you choose).]
See also this thread from help-gnu-emacs#gnu.org. It is pretty much the same question as yours, I think. My replies there were pretty much the same as my reply here, but there are also replies from others that might help you as well.
Try
M-x speedbar
That might appeal to you
Another view-mode solution on top of ag-mode lists. I couldn't find a question for ag-mode, maybe this helps someone generalize a ffap-preview for any mode.
(defun directory-ag-results ()
(save-excursion
(goto-char (point-min))
(search-forward "\"")
(setq a (point))
(search-forward "\"")
(setq b (- (point) 1))
(buffer-substring-no-properties a b)))
(defun search-item-path ()
(let ((dir (directory-ag-results))
(file-parts (split-string (substring-no-properties (thing-at-point 'filename)) ":")))
(concat dir (nth 0 file-parts))))
(defun search-item-line ()
(let ((file-parts (split-string (substring-no-properties (thing-at-point 'filename)) ":")))
(- (string-to-number (nth 1 file-parts)) 1)))
(defun view-current ()
"Quickly view the current file in another window."
(if (not (window-parent))
(split-window)) ; create a new window if necessary
(let ((file (search-item-path))
(line (search-item-line))
(dbuffer (current-buffer)))
(other-window 1) ; switch to the other window
(unless (equal dbuffer (current-buffer)) ; don't kill the dired buffer
(if (or view-mode (equal major-mode 'dired-mode)) ; only if in view- or dired-mode
(kill-buffer))) ; ... kill it
(let ((filebuffer (get-file-buffer file)))
(if filebuffer ; does a buffer already look at the file
(switch-to-buffer filebuffer) ; simply switch
(progn
(view-file file) ; ... view it
(goto-char (point-min))
(next-line line)))
(other-window -1))))
(defun next-view-current ()
(interactive)
(next-line)
(view-current))
(defun previous-view-current ()
(interactive)
(previous-line)
(view-current))
(define-key ag-mode-map (kbd "M-p") 'previous-view-current)
(define-key ag-mode-map (kbd "M-n") 'next-view-current)
This is the one thing I think Sublime does better than Emacs. Blasphemy, I know! I like the "q to exit" feel of view-mode, rather than timer-based solutions, and like scrolling around a previewed file. This snippet navigates to the line number found in the search results, optimizing for browsing speed.
Note about the code: I tried polyfilling vc-root-dir from Emacs 25, but it doesn't really make sense for ag-mode since ag-mode's buffer is outside the repo you're searching in. I ended up pulling the root dir from the top of the "ag search" buffer.
Early stages. Improvements welcome.
Demo
Edit: It works for ag-mode, not dired. Demo gif.
Credits: abo-abo, user2979331
In the interest of keeping StackOverflow up to date, the package peep-dired does everything posted in the other answers, and I’m sure there are other packages as well. You don’t have to maintain copypasted or home-rolled lisp for this job.

Select the previously-selected window in emacs

I need an emacs built-in function or elisp function that can take me to the previously-selected window. I thought that (select-window (get-lru-window)) would do it, but if I run it several times, seems to just cycle between windows instead of swapping back and forth between them, which is what I expect.
Any other ideas?
There doesn't seem to be a way to get the most recently selected window in emacs (as opposed to the least recently used returned by get-lru-window). Internally emacs tracks use_time on windows, and get-lru-window uses that to find the "oldest" window. But unfortunately that is not exposed in elisp.
The window list is ordered in cyclic window ordering which doesn't help in your case.
The buffer-list is however ordered most-to-least recently used buffer (or not really strictly, there is a (bury-buffer) function to move a buffer last).
This means that, if you can transform your problem into something like "how can I switch to the buffer in a different window that was most recently the selected buffer", it should be possible.
One way would be to do something like this:
(defun switch-to-previous-buffer-in-a-different-window ()
(interactive)
(let* ((otherbuf (other-buffer (current-buffer) t))
(otherwin (get-buffer-window otherbuf)))
(if otherwin
(select-window otherwin)
(message "Last buffer (%s) is not currently visible" (buffer-name otherbuf)))))
Or the shorter, and more featureful:
(defun switch-to-previous-buffer-possibly-creating-new-window ()
(interactive)
(pop-to-buffer (other-buffer (current-buffer) t)))
Here other-buffer is used to get the most recently used buffer (except current-buffer). This should work fine as long as you don't switch buffers in the windows, because then other-buffer will no longer return the buffer in the other window, but the buffer you switched from in current window.
So instead of using other-buffer lets walk the buffer-list ourself to find the best candidate:
(defun switch-to-the-window-that-displays-the-most-recently-selected-buffer ()
(interactive)
(let* ((buflist (buffer-list (selected-frame))) ; get buffer list in this frames ordered
(buflist (delq (current-buffer) buflist)) ; if there are multiple windows showing same buffer.
(winlist (mapcar 'get-buffer-window buflist)) ; buf->win
(winlist (delq nil winlist)) ; remove non displayed windows
(winlist (delq (selected-window) winlist))) ; remove current-window
(if winlist
(select-window (car winlist))
(message "Couldn't find a suitable window to switch to"))))
Hope this helps.
If the last window switch was done programmatically, then it is possible to select the previously selected window.
(defun your-function ()
(interactive)
(let ((sw (selected-window)))
(do-something-useful-and-switch-window)
(select-window sw)))
If the last window switch was done manually, then it should be possible to overload the window switching command to update a global list of window selection order, which is then used to switch back.
(defun gs/pop-to-previous-window ()
(interactive)
(let ((win (get-mru-window t t t)))
(select-window win)))

How can I switch focus after buffer split in emacs?

I would like that after splitting the window (C-x 3 or C-x 2) to be able to automatically get to cursor in the new opened buffer (the other than the current). How can I achieve this behavior ?
You can switch between buffers with C-x o. As to do that automatically I don't think there is an existing command for that.
You can do it like this:
(global-set-key "\C-x2" (lambda () (interactive)(split-window-vertically) (other-window 1)))
(global-set-key "\C-x3" (lambda () (interactive)(split-window-horizontally) (other-window 1)))
In Emacs 24.3.1 it works if you change the argument 1 for 0.
!!!DO NOT USE THIS ANSWER!!! -- as pointed out in the comments, advising split-window can lead to undesired side-effects.
I recommend Bozhidar Batsov's answer instead.
Put the following in your .emacs file:
(defadvice split-window (after move-point-to-new-window activate)
"Moves the point to the newly created window after splitting."
(other-window 1))
As well as splitting the frame manually with C-x 2 or C-x 3, buffers are also automatically "popped-up" some times. These are also not selected/active by default.
This can be fixed by changing the function used to split a window. It's set to split-window-sensibly by default, but you can set it to your own function that calls split-window-sensibly and then selects the buffer.
Unfortunately, though, this has the side-effect of selecting the *Completions* buffer when you hit TAB in the minibuffer. So, it's worth checking to see if the minibuffer is active and not switching in this case. I'd bet there are other such undesirable scenarios as well. I'll try to update this post as and when I find them.
;; after splitting a frame automatically, switch to the new window (unless we
;; were in the minibuffer)
(setq split-window-preferred-function 'my/split-window-func)
(defun my/split-window-func (&optional window)
(let ((new-window (split-window-sensibly window)))
(if (not (active-minibuffer-window))
(select-window new-window))))
(Works with Emacs 24.5.1.)
My thought of when you would want to follow the window after a split-window was when it had the same buffer like in the following code:
(defun split-window--select-window (orig-func &rest args)
"Switch to the other window after a `split-window'"
(let ((cur-window (selected-window))
(new-window (apply orig-func args)))
(when (equal (window-buffer cur-window) (window-buffer new-window))
(select-window new-window))
new-window))
(advice-add 'split-window :around #'split-window--select-window)
Simple
C-x o will help you switch to the "other" buffer.

Windows configuration to registers

I'm starting to use quite heavily the commands C-x r w and C-x r j to store windows configuration to registers and recall them at a later point, but I find a bit annoying that the cursor positions are stored as per the time when the window configuration was saved.
Basically I would like that the cursor positions are not stored (or are updated automatically), so that whenever I "jump" to a stored window configuration I get the same view as when I last visited it, not as when I created it.
Any ideas?
Ángel
I also found this very annoying and just coded up a solution. Store the window config using the normal functionality (current-window-configuration or window-configuration-to-register). Then, before applying the saved window config (or register),
Store the points of all open buffers.
Restore the window config.
Apply the stored points to the current windows.
The code below does this. You'll have to hook up restore-window-configuration to the register code yourself though.
(defun buffer-point-map ()
(save-excursion
(mapcar (lambda (buffer) (cons (buffer-name buffer)
(progn (set-buffer buffer) (point))))
(buffer-list))))
(defun apply-buffer-points (buff-point-map)
(mapc (lambda (window) (let* ((buffer (window-buffer window))
(buffer-point (cdr (assoc (buffer-name buffer) buff-point-map))))
(when buffer-point (set-window-point window buffer-point))))
(window-list))
nil)
(defun restore-window-configuration (window-config)
(let ((points (buffer-point-map)))
(set-window-configuration window-config)
(apply-buffer-points points)))
If you take a look into a source code
(defun window-configuration-to-register (register &optional arg)
...
(set-register register (list (current-window-configuration) (point-marker))))
you'll see that it stores a point as the second argument.
Just re-define it like
(defun my-window-configuration-to-register (register &optional arg)
(interactive "cWindow configuration to register: \nP")
(set-register register (list (current-window-configuration) nil)))
and redefine a C-x r w shortcut as well to use my-window-configuration-to-register
(define-key (current-global-map) (kbd "C-x r w") 'my-window-configuration-to-register)
Or define an advice
(defadvice window-configuration-to-register (after window-configuration-to-register-no-point activate)
"Avoid storing current buffer's position in the register. We want to stay on the last used position, not to jump to the saved one"
(set-register register (list (current-window-configuration) nil)))
The only problem is that it brings up an error message when you jump to it. You may redefine jump-to-register to avoid it
I'll add another answer which uses different approach.
Before you jump to another register you may store the current window configuration. This way it will store your latest buffers position just before you jump.
This will not work in all cases, however. For example if you just switch to another buffer or create a buffer with M-x dired or something then it will not store the current window config.
(defvar current-window-conf-register nil)
(defadvice window-configuration-to-register (after window-configuration-to-register-current-reg activate)
(setq current-window-conf-register register))
(defadvice jump-to-register (before jump-to-register-store-window-conf activate)
(if current-window-conf-register (window-configuration-to-register current-window-conf-register))
(setq current-window-conf-register register))
As a indirect answer to your question, you might consider using revive.el instead, which supports saving and restoring window configurations across Emacs restart, but doesn't (I believe) store the point.