how to browse through recent files (not just filenames) in Emacs? - emacs

I use an Emacs library called buffer-stack to page through my currently open buffers. It's great because it allows me to exclude uninteresting buffers like Messages and browse through only the buffers with content I've created. I browse through these buffers with a single keystroke, A-right.
I also use Ido-mode to browse through the names of recently opened files.
However, I'd like to be able to browse through not just the filenames, but the actual files, preferably with a single keystroke.
How can I browse through recently opened files?

You can use helm-recentf and its persistent-action for this purpose.
You can select recent file with helm-recentf as below.
And you can see file content by pressing Ctrl-z(persistent-action).
you press Ctrl-z, then show it content to another window(in this case upper window) temporary.
Please see official document, if you learn about helm

Here are two possible solutions (depending on exactly the use case you want).
(defun zin/open-recent-file ()
"Open the most recent currently closed file.
This will omit currently open files, instead it will retrieve the
next oldest file in recentf-list."
(interactive)
(let* ((count 0)
(recent recentf-list)
(r-length (length recent))
(buffers (mapcar 'buffer-file-name (buffer-list))))
;; Compare next file on the list to open buffers, if open skip it.
(while (member (nth count recent)
buffers)
(setq count (1+ count))
(if (= r-length count)
(error "All recent buffers already open")))
(find-file (nth count recent))))
(lexical-let ((recent-count 0))
(defun zin/visit-recent-file ()
"Visit files on the recentf-list in descending order.
This will work backwards through recentf-list visiting each file
in turn."
(interactive)
;; If last command was not to cycle through the files, then start
;; back at the first in the list.
(unless (eq last-command 'zin/visit-recent-file)
(setq recent-count 0))
;; If current buffer is the current entry on the list, increment.
(if (equal (buffer-file-name) (nth 0 recentf-list))
(setq recent-count (1+ recent-count)))
;; Error if all entries have been processed
(if (= recent-count (length recentf-list))
(error "At oldest recent buffer"))
;; Open appropriate file.
(find-file (nth recent-count recentf-list))))
The first will go through the list of recent files (recentf-list) and open the next unopened file. The second will use recentf-list to cycle to the next buffer in the list, until all have been visited then erroring out (since the list order will change as files are reopened).
To have it restart cycling when it reaches the end, just change the (error ...) to
(setq recent-count 0)

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.

In Emacs, is there a command to visit the most recently opened file?

In Emacs, is there a command to open the most recently opened file? Like a visit-most-recent-file?
Note that I don't want to view a LIST of recent files and then select one. I want to automatically visit the most recently opened one.
It would be great to visit a recently-opened file (that's no longer in a current buffer) with a single keystroke. And then be able to visit the next most recently opened file by invoking the keystroke again, and so on.
So that by pressing that keystroke four times (e.g. A-UP), I could automatically open the top four files on my recent files list.
I can kind of sort of do this already by browsing through recent files, by pressing C-x C-f UP RET, but it would be cool to do it in a single keystroke (e.g. A-UP).
Building off of pokita's answer,
(defun visit-most-recent-file ()
"Visits the most recently open file in `recentf-list' that is not already being visited."
(interactive)
(let ((buffer-file-name-list (mapcar 'buffer-file-name (buffer-list)))
most-recent-filename)
(dolist (filename recentf-list)
(unless (memq filename buffer-file-name-list)
(setq most-recent-filename filename)
(return)))
(find-file most-recent-filename)))
I haven't tested this very much.
You can do this by using the recentf package:
(require 'recentf)
(defvar my-recentf-counter 0)
(global-set-key (kbd "<M-up>")
(lambda ()
(interactive)
(setq my-recentf-counter (1+ my-recentf-counter))
(recentf-open-most-recent-file my-recentf-counter)))
You will probably face the problem that there are files in the "recent" list which you are not interested in (temporary stuff that was saved upon exiting Emacs). Use the recentf-exclude variable to exclude those files from the list of recently opened files.

How to hide extra information in Emacs

I want to open an XML file and process it in a special way in Emacs. (Let's say a major mode which is customized to open XML files and process it and present it in a special way)
What I want to do is to hide the extra markup tags in XML and show just the content to the user. Can anyone advice me how I should do this?
`<name id=22> Luke </name>`
=> I just want "Luke" to be shown.
One way to do this would be to use a regular expression to extract the element information from your XML, and then open a temporary buffer for viewing into which you paste that element information. i'm not sure that narrowing is granular enough to hide the markup and display only the element information.
Having said that, an alternative to the temporary buffer approach would be to extract the element information, paste it into the bottom of the file, and then narrow to just that portion of the file so that the source markup is invisible.
The function below does approximately what I have in mind:
(defun show-xml-entities ()
(interactive)
(save-excursion
(let ((old-max (point-max))) ;; save current end of buffer
(goto-char (point-min)) ;; go to beginning of buffer
(while (re-search-forward ">\\([^<>]+\\)<" nil t) ;; search for elements until not found
(when (> (length (match-string-no-properties 1)) 0) ;; if match is non-zero length
(setq temp (point-marker)) ;; save end of match
(goto-char (point-max)) ;; go to end of buffer
;; paste current match to end of buffer
(insert (concat (buffer-substring-no-properties (match-beginning 1) (match-end 1))))
(goto-char (marker-position temp)) ;; return to end of current match
)
)
(narrow-to-region old-max (point-max))) ;; narrow to newly pasted element text
)
)
Logical steps would be
- calculate starting buffer end position (point-max) and sav in a var
- loop through your XML, collecting your entity information and pasting it after the saved position
- when done call (narrow-to-region original-point-max (point-max)). This will hide all the XML so that only your entity text is visible.
M-x sgml-hide-tags RET
see in menu SGML section VIEW some more related commands

Emacs: reopen buffers from last session on startup?

Every day I start up emacs and open the exact same files I had open the day before. Is there something I can add to init.el file so it will reopen all the buffers I was using when I last quit emacs?
You can use the Emacs Desktop library:
You can save the desktop manually with
the command M-x desktop-save. You can
also enable automatic saving of the
desktop when you exit Emacs, and
automatic restoration of the last
saved desktop when Emacs starts: use
the Customization buffer (see Easy
Customization) to set
desktop-save-mode to t for future
sessions, or add this line in your
~/.emacs file:
(desktop-save-mode 1)
Although I suspect the question was looking for the emacs "desktop" functionality (see above answer), Lewap's approach can be useful if the set of files one uses really is the exact same file set. In fact, one can go a step further and define 'profiles' if one has different sets of regularly used files... Quickie example:
(let ((profile
(read-from-minibuffer "Choose a profile (acad,dist,lisp,comp,rpg): ")
))
(cond
((string-match "acad" profile)
(dired "/home/thomp/acad")
(dired "/home/thomp/acad/papers")
)
((string-match "lisp" profile)
(setup-slime)
(lisp-miscellany)
(open-lisp-dirs)
)
((string-match "rpg" profile)
(find-file "/home/thomp/comp/lisp/rp-geneval/README")
(dired "/home/thomp/comp/lisp/rp-geneval/rp-geneval")
... etc.
If you find that you regularly switch back and forth between different sets of regularly-used files as you work, consider using perspectives and populating each perspective with the desired set of regularly-used files.
For storing/restoring the buffers/tabs (specifically elscreen tabs): I use elscreen and the way I manage storing/restoring the desktop session and the elscreen tab configuration is the following code in my .emacs file (the names used are self-explanatory and if the storing/restoring functions should not be executed every time emacs starts just comment out the lines with "(push #'elscreen-store kill-emacs-hook)" and "(elscreen-restore)"):
(defvar emacs-configuration-directory
"~/.emacs.d/"
"The directory where the emacs configuration files are stored.")
(defvar elscreen-tab-configuration-store-filename
(concat emacs-configuration-directory ".elscreen")
"The file where the elscreen tab configuration is stored.")
(defun elscreen-store ()
"Store the elscreen tab configuration."
(interactive)
(if (desktop-save emacs-configuration-directory)
(with-temp-file elscreen-tab-configuration-store-filename
(insert (prin1-to-string (elscreen-get-screen-to-name-alist))))))
(push #'elscreen-store kill-emacs-hook)
(defun elscreen-restore ()
"Restore the elscreen tab configuration."
(interactive)
(if (desktop-read)
(let ((screens (reverse
(read
(with-temp-buffer
(insert-file-contents elscreen-tab-configuration-store-filename)
(buffer-string))))))
(while screens
(setq screen (car (car screens)))
(setq buffers (split-string (cdr (car screens)) ":"))
(if (eq screen 0)
(switch-to-buffer (car buffers))
(elscreen-find-and-goto-by-buffer (car buffers) t t))
(while (cdr buffers)
(switch-to-buffer-other-window (car (cdr buffers)))
(setq buffers (cdr buffers)))
(setq screens (cdr screens))))))
(elscreen-restore)
There are useful enhancements you can make to the basic desktop feature. Particular handy (IMO) are methods of auto-saving the desktop during the session, as otherwise if your system crashes you will be stuck with the desktop file you had started that session with -- pretty annoying if you tend to keep Emacs running for many days at a time.
http://www.emacswiki.org/emacs/DeskTop
The wiki also has useful information about persisting data between sessions in general:
http://www.emacswiki.org/emacs/SessionManagement
For desktops specifically, I thought that Desktop Recover looked particularly promising, however I've not yet tried it out.
(find-file-noselect "/my/file") will open it silently, ie w/o raising the buffer. Just saying.
EDIT This command is not interactive ; To test it you have to evaluate the expression, for example by positioning the cursor after the last parenthesis and hitting C-x C-e
Downvoting this is not cool ; this command definitely works and is in the scope of the question.