I maintain a diary (internal blog containing thoughts to remember) in org-mode, and sometimes, as i study Emacs, i store learned skills and tricks with references to info files.
Currently i do the following. I open the needed info file, press c to copy current node name, press < s TAB - that is an easy template which unwraps into a src-block. Then i add lisp expression and paste node name and finally the link looks like this:
#+begin_src emacs-lisp
(info "(org) Properties and Columns")
#+end_src
When i need to view the info file, i put cursor after lisp sexp and press C-x C-e (eval-last-sexp).
This process is tedious and inelegant. What is the best way to embed links to info files in org-mode?
Edit: I've found how one can add links to info nodes. Org-mode manual on External links describes these equivalent methods using links:
[[info:org#Tags]]
[[elisp:(info "(org) Tags")]]
With the first variant i'm not sure how to automatically transform (org) Tags in org#Tags. How can i further simplify this process?
You do it as in any of the supported link types (see the "Handling
links" section in the manual). In the info file, you say M-x org-store-link,
(bind it to C-c l as suggested in the manual) and then in your org
file, you insert the link with C-c C-l. There you just have to
select the link to your info file from the list of stored links.
org-store-link says "Cannot link to a buffer which is not visiting a file" when visiting an Info page because Info sets the buffer-name to *info* and the buffer-file-name to nil. To work around this, the community contributed example of how to add linking to man pages (http://orgmode.org/manual/Adding-hyperlink-types.html) can be modified slightly:
;; Modified version of contrib/lisp/org-man.el; see
;; (http://orgmode.org/manual/Adding-hyperlink-types.html#Adding-hyperlink-types)
(require 'org)
(org-add-link-type "info" 'org-info-open)
(add-hook 'org-store-link-functions 'org-info-store-link)
(defcustom org-info-command 'info
"The Emacs command to be used to display an info page."
:group 'org-link
:type '(choice (const info)))
(defun org-info-open (path)
"Visit the infopage on PATH.
PATH should be a topic that can be thrown at the info command."
(funcall org-info-command path))
(defun org-info-store-link ()
"Store a link to an info page."
(when (memq major-mode '(Info-mode))
;; This is a info page, we do make this link
(let* ((page (org-info-get-page-name))
(link (concat "info:" page))
(description (format "Infopage for %s" page)))
(org-store-link-props
:type "info"
:link link
:description description))))
(defun org-info-get-page-name ()
"Extract the page name from Info in a hackish way."
;; This works for `Info-mode'.
;; Hackity-hack: copy the node name into the kill ring.
(Info-copy-current-node-name)
;; Just return the kill.
(current-kill 0))
(provide 'org-info)
The important bit is near the end: since the info node name is not directly accessible (not that I could easily find), we can work around it by calling Info-copy-current-node-name to put it in the kill-ring, then return the first entry in the kill-ring (which should be the just inserted node name).
The step that should work
- go to info node you need then press just 'c' (node-name will be
entry to kill ring)
- on your org source-file go to point you need to insert the link
press C-c,C-l
- press Tab then select elisp: from prompted buffer shown (or any kind
of link you need).Now your prompt in mini-buffer say elisp:
- entry this context after that ':' (info "^") ,let ^ be your
node-name yank back by C-y
- press Ret ,then you'll be ask for some description just fill it with
your own. Now you are done with it ,but still don't know what happen
really.
- M-x,visibility-mode,And there how to write that content manually and
we are now came to conclusion that "%20" must be replace every
occurence of space in the context.
eg.==> do it yourself ,see it yourself
- switch back your visibility-mode
GoodLuck
Related
This is a very simple request: I want to create a new, blank file without giving it a name (yet). I can use the scratch buffer but there's only one. I can C-x C-f and open a new file, but then I have to give it a name and path. If I'm just writing notes to myself or sketching out ideas, I don't want to have to give it a name. How do I create a new, empty, unnamed file?
You can create a new buffer with: C-xb and type in the buffer name and it will create a new buffer with a name that you choose.
If you want to save that buffer, just hit C-x w to create the file with its contents to a desired location.
My recommendation is that you give org-mode a try. It will do what want among a million other things.
Give it a name. Just don't save it.
Not what you wanted to hear, but this is the Emacs way.
Use C-x C-f, giving the (to-be-file-visiting) buffer a name. Edit the text. Do not use C-x C-s to save the buffer to the file (i.e., to disk).
Note that you can first put yourself in a directory whose contents you don't care about, so that if you accidentally do save the buffer there then you can easily find, recognize and toss the file. To change directories, you can use M-x cd. Or just do it by editing the directory part when you first use C-x C-f. Or use C-x d to put yourself in a Dired buffer for the directory.
If you don't want to take the chance of accidentally hitting C-x C-s and thus saving your edits, then use C-x b instead of C-x C-f. You are (even here) prompted for the buffer name. Giving it a new name (not the name of an existing buffer) creates a new buffer. In this case, if you use C-x C-s then Emacs prompts you for the file location to save the buffer in.
Why would you want to use C-x C-f instead of C-x b, if you might not want to save the buffer? Providing a file extension in the file name you give automatically puts the buffer in the proper major mode (typically). Otherwise (for C-x b) you need to put the buffer in the mode you want.
Buffer *scratch* is by default in Lisp-Interaction mode, which is similar to Emacs-Lisp mode (but not the same).
In every other text editor or word processor the intuition is to create a “new file” or a “new buffer”, not to switch to idiosyncratic *scratch* buffer. For example, you write quick notes or thoughts in several different buffers to keep trace of them—later you decide if you throw them away or save them. Or you manipulate a snippet of text or code, but you don't want to change the original buffer, so you just copypaste it to a new temporary buffer.
*scratch* is set to Lisp Interaction mode, but if I want to quickly evaluate some Elisp code, I could eval it running eval-expression (Alt+:) or in Elisp interpreter IELM (Alt+x Enter ielm). Also, if you close *scratch* buffer, it doesn't ask you to save it, so you can accidentally lose all your work. Drew's traditional solution seems too sub-optimal. And I don't buy the argument that “this is how you do it in Emacs”. Emacs is a customizable editor, so you can and should create whatever workflow is comfortable for you.
That's how ErgoEmacs solves it, buy creating a new-empty-buffer command. You can implemented like this:
(defun new-empty-buffer ()
"Opens a new empty buffer."
(interactive)
(switch-to-buffer (generate-new-buffer "untitled"))
(funcall initial-major-mode)
(put 'buffer-offer-save 'permanent-local t)
(setq buffer-offer-save t))
The variable buffer-offer-save resets every time you change a major mode, therefore you need to annotate it with permanent-local. It also prompts only when you exit Emacs. I think it is intuitive for it to also ask, when you close a modified untitled buffer, therefore see my solution on how to upgrade kill-buffer to prompt before closing a modified buffer.
ErgoEmacs revamps the default keybindings completely and has new-empty-buffer bound to Ctrl+N, like in almost all software. Change variable initial-major-mode if you want the new buffer to have another mode on start.
See also:
Emacs: Problems of the Scratch Buffer # Xah Lee
Emacs: New Empty Buffer # Xah Lee
You can try the following snippet, just add it to your .emacs
(defun new-file-tmp()
"Create a new empty file."
(interactive)
(let ((buf (generate-new-buffer "untitled")))
(switch-to-buffer buf)
(put 'buffer-offer-save 'permanent-local t)
(setq buffer-offer-save t)))
(defun tool-bar-local-item-pre (icon def key map after_item &rest props)
"Add an item to the tool bar in map MAP.
ICON names the image, DEF is the key definition and KEY is a symbol
for the fake function key in the menu keymap. Remaining arguments
PROPS are additional items to add to the menu item specification. See
Info node ‘(elisp)Tool Bar’. The item is added after AFTER_ITEM.
ICON is the base name of a file containing the image to use. The
function will first try to use low-color/ICON.xpm if ‘display-color-cells’
is less or equal to 256, then ICON.xpm, then ICON.pbm, and finally
ICON.xbm, using ‘find-image’."
(let* ((image-exp (tool-bar--image-expression icon)))
(define-key-after map (vector key)
`(menu-item ,(symbol-name key) ,def :image ,image-exp ,#props) after_item)
(force-mode-line-update)))
(when (boundp 'tool-bar-map)
(tool-bar-local-item-pre "new" 'new-file-tmp 'new-file-tmp tool-bar-map
'new-file :label "" :help "New untitled File")
(define-key tool-bar-map (vector 'new-file) nil)
;; comment the above line if you want to keep the button for the default behavior
)
(global-set-key (kbd "C-n") 'new-file-tmp)
It defines a new command which creates new empty buffers
Then the code binds it to the top left button of the toolbar, if you are in gui mode, and to the Control-n shortcut.
You can check the post on my site about it.
disclaimer: it's my site
A buffer and a file are not the same thing.
terminology
Regarding buffers,
The text you are editing in Emacs resides in an object called a
buffer. Each time you visit a file, a buffer is used to hold the file's text.
Regarding files,
The operating system stores data permanently in named files, so most
of the text you edit with Emacs comes from a file and is ultimately
stored in a file.
Buffers and files are related through visiting,
Visiting a file means reading its contents into an Emacs buffer so you
can edit them. Emacs makes a new buffer for each file that you visit.
answering the question
Unless I'm mistaken, technically speaking, your question, as written, can't be answered. Pedantically speaking, there's no such thing as (or little practical use for) an unnamed file. A file is a handle for something stored on disk. If you have no handle, then why make a file?
The question can then be interpreted as having two possible meanings1.
1. Making a new buffer (without regard to name)
A new buffer must have a name. An unsaved buffer can be saved to file with a given name using write-file (C-x C-w). You will be prompted for a path/name. Once written, the buffer update to be visiting the file you just wrote.
Since the name of the buffer doesn't matter (until you write it to file), here's a function which creates buffers named *scratch1*, *scratch2*, ... .
(defun create-scratch-buffer ()
"Create a new numbered scratch buffer.
Taken from URL `https://stackoverflow.com/a/21058075/5065796' "
(interactive)
(let ((n 0)
bufname)
(while (progn
(setq bufname (concat "*scratch"
(if (= n 0) "" (int-to-string n))
"*"))
(setq n (1+ n))
(get-buffer bufname)))
(switch-to-buffer (get-buffer-create bufname))
(org-mode)
(if (= n 1) initial-major-mode)))
2. Making a new file (without regard to name)
As hinted at in the new buffer solution, new files can be created with write-file.
When called interactively (M-x make-random-file), this function prompts for a directory. It then writes an empty file named something random like tmp-17388716387615.txt.
(defun make-random-file (dir)
"Make a random file in DIR."
(interactive "DDir: ")
(let* ((filename (concat "tmp-" (int-to-string (random t)) ".txt"))
(filepath (concat dir filename)))
(write-region "" nil filepath nil 'silent nil 'excl)))
As always, if the code above doesn't make sense, look at the documentation for functions and variables with C-h f and C-h v, respectively. And/or read the Introduction to Programming in Emacs Lisp.
1 It was the second meaning which I was searching for solutions to when I found this as the top search engine hit. Apologies if this was a bit obtuse. Figured it was better to share my solutions with y'all than not. :)
I'd like the corresponding, closing HTML tag to be automatically inserted whenever I open one.
So if I type
<div>
I should get
<div></div>
Without having to call to sgml-close-tag myself.
How to achieve this?
Rather than calling a hook function after every single key-stroke, it makes sense to only call it after a > was typed. This can be achieved by rebinding the > character in the keymap that sgml-mode uses.
In addition, sgml-close-tag shouldn't get called if the tag is already closed. Therefore, the following code adds a simple regexp check for that:
(defun my-sgml-insert-gt ()
"Inserts a `>' character and calls
`my-sgml-close-tag-if-necessary', leaving point where it is."
(interactive)
(insert ">")
(save-excursion (my-sgml-close-tag-if-necessary)))
(defun my-sgml-close-tag-if-necessary ()
"Calls sgml-close-tag if the tag immediately before point is
an opening tag that is not followed by a matching closing tag."
(when (looking-back "<\\s-*\\([^</> \t\r\n]+\\)[^</>]*>")
(let ((tag (match-string 1)))
(unless (and (not (sgml-unclosed-tag-p tag))
(looking-at (concat "\\s-*<\\s-*/\\s-*" tag "\\s-*>")))
(sgml-close-tag)))))
(eval-after-load "sgml-mode"
'(define-key sgml-mode-map ">" 'my-sgml-insert-gt))
If you like paredit (and if you're an emacs user, chances are you do), you may be interested in tagedit, an emacs package written by Magnar Sveen that provides paredit-like features for editing html.
The library is here: https://github.com/magnars/tagedit, and can be installed through Melpa/Marmalade (package-install tagedit).
If you enable the experimental features (tagedit-add-experimental-features), then it will automatically close tags for you and keep the corresponding closing tag text matching the opening tag text. That's on top of being able to splice, slurp, barf and all the other crazy things that paredit lets you do when working with balanced expressions...I think it's great!
I'm using yasnippet for this purpose.
To type shortcuts this answer, like <kbd>C-o</kbd>, I have the following snippet:
# -*- mode: snippet -*-
# name: kbd
# key: kbd
# --
<kbd>$0</kbd>
So I type kbdC-o and it get's expanded to <kbd></kbd> with cursor
right in the middle. You can have the same behavior for div.
You may eval this on your sgml-buffer or add ii to your sgml-hook:
(add-hook 'post-self-insert-hook
(lambda () (and (eq (char-before) ?>) (sgml-close-tag))) nil t)
Whenever you insert a ">", the function sgml-close-tag will be run for you
I tried out Sublime Text 2 recently, and I found Goto Anything superbly useful for navigating source code (Ctrl-P file#symbol seems to work really well). Is there something similar for Emacs? Preferably something that just works, without a ton of custom elisp.
What I've tried so far:
I've seen Helm and Anything, but as far as I understand neither of them is capable of actual "instant" search (see edit below).
I've used multi-occur-in-matching-buffers, but it too seems unable to satisfy the "instant" criterion.
imenu / idomenu works well for single files, but doesn't work across files.
I currently use #2 and #3 together, as a poor substitute for Goto Anything.
If not an exact clone of Goto Anything, then I could make do with a naive instant search solution (one that searches for a given string across all open buffers and displays results dynamically). So that's acceptable too.
I use Emacs 24.2, so any v24-only elisp is also fine.
EDIT: I gave Helm another shot, at event_jr's suggestion, and I found that it does support instant searching across all open buffers. helm-multi-occur + helm-follow-mode comes surprisingly close to meeting my needs, the only minor issues being (at the risk of sounding nit-picky):
I haven't found a way to turn on helm-follow-mode automatically when I run helm-multi-occur. I have to invoke it manually with C-c C-f. Anyone care to take a shot at this with a snippet of elisp? (see edit #2 below)
it isn't "intelligent" like ST2's Goto Anything (i.e., it doesn't understand "symbols" in source code, like Goto Anything does).
EDIT #2: Now I've got most of Goto Anything, thanks to event_jr's answer below (and of course, thanks to Helm's creator, Thierry Volpiatto). I recommend it heartily to anyone looking for a similar feature. Below is the elisp I'm currently using:
;; instant recursive grep on a directory with helm
(defun instant-rgrep-using-helm ()
"Recursive grep in a directory."
(interactive)
(let ((helm-after-initialize-hook #'helm-follow-mode))
(helm-do-grep)))
;; instant search across all buffers with helm
(defun instant-search-using-helm ()
"Multi-occur in all buffers backed by files."
(interactive)
(let ((helm-after-initialize-hook #'helm-follow-mode))
(helm-multi-occur
(delq nil
(mapcar (lambda (b)
(when (buffer-file-name b) (buffer-name b)))
(buffer-list))))))
;; set keybindings
(global-set-key (kbd "C-M-s") 'instant-search-using-helm)
(global-set-key (kbd "C-M-S-s") 'helm-resume)
(global-set-key (kbd "C-M-g") 'instant-rgrep-using-helm)
Just use helm.
It is perhaps more configuration than you asked for, but once you get it
configured how you like, it should be quite comfortable. Very much like Emacs
;).
And you should file a bug with Thierry for getting some more newbie friendly
defaults. He is quite responsive with issues.
helm-multi-occur
Primarily multi-buffer interactive "occur" is provided through
helm-multi-occur. If you execute the command, you'll notice that you have
to pick some buffers first (use C-SPC to select from the list,
M-SPC to select all). Then you can enter your query at the next
prompt. It's easy to make your own version that skips the buffer selection
like so:
(eval-after-load "helm-regexp"
'(setq helm-source-moccur
(helm-make-source "Moccur"
'helm-source-multi-occur :follow 1)))
(defun my-helm-multi-all ()
"multi-occur in all buffers backed by files."
(interactive)
(helm-multi-occur
(delq nil
(mapcar (lambda (b)
(when (buffer-file-name b) (buffer-name b)))
(buffer-list)))))
helm-buffers-list
Often you don't care about the exact occurrences of the query string, but want a
list of all buffers that contain it.
helm-buffers-list has some tricks up its sleeve. The first symbol you
specify is filtering by major-mode, and you can use the "#" prefix to narrow
the list to buffers that contain a string.
To wit, "ruby #prompt" will show you a list of buffers whose major-mode
contains "ruby" and whose contents contains "prompt". Or you can just use "#prompt" to show all buffers that contain "prompt".
Powerful and comfortable once you get used to it.
EDIT modified my-helm-multi-all to enable helm-follow-mode.
EDIT 2 update helm-follow-mode code to reflect helm changes.
EDIT 3 updated again to reflect helm changes
Emacs has Projectile satisfy your need:
jump to a file in project
multi-occur in project buffers
Heml is far from the fuzzy searching of ST3.
Fiplr looks promising but doesn't work on my laptop (see first issue on the github)
Simp.el looks like Fiplr but doesn't work either on my end.
Projectile works for me! Here's your solution!
I used also ido-mode and flx-ido for the fuzzy searching,
and for the vertical way of displaying results I use this in my .emacs:
;; Display ido results vertically, rather than horizontally
(setq ido-decorations (quote ("\n-> " "" "\n " "\n ..." "[" "]" " [No match]" " [Matched]" " [Not readable]" " [Too big]" " [Confirm]")))
(defun ido-disable-line-truncation () (set (make-local-variable 'truncate-lines) nil))
(add-hook 'ido-minibuffer-setup-hook 'ido-disable-line-truncation)
(defun ido-define-keys () ;; C-n/p is more intuitive in vertical layout
(define-key ido-completion-map (kbd "C-n") 'ido-next-match)
(define-key ido-completion-map (kbd "C-p") 'ido-prev-match))
(add-hook 'ido-setup-hook 'ido-define-keys)
Icicles offers some features that are similar to what it seems you are looking for.
C-x b and C-x C-f, to choose buffers or files, allow multi-completion: you can type a pattern to match the buffer/file name and/or a pattern to match content in the buffer/file. Candidates are filtered incrementally as you type (what you call "instant" is what Emacs calls "incremental"). You can refine either or both search patterns progressively, narrowing the choices in different ways. You can visit any number of buffers/files that match, at the same time. You can also use the same method to search the marked files in Dired: C-F.
C-c `(icicle-search) incrementally searches across multiple buffers or files. Again, progressive refinement etc.
The main difference between #1 and #2 is this:
For #1, you just want to find matching buffers or files. You don't care immediately about finding particular occurrences --- any match suffices.
For #2, you provide the buffers or files to search, and you want to navigate among search hits.
You can also use #1 to locate the buffers and files you want, then search their contents: The content-matching pattern you last used is available as the search pattern for Isearch (C-s).
for emacs I customize and modify this solution (for use install helm):
(defun helm-occur-from-point (initial-value)
"Invoke `helm-occur' from point."
(interactive)
(let ((input initial-value)
(bufs (list (buffer-name (current-buffer)))))
;; (isearch-exit)
(helm-occur-init-source)
(helm-attrset 'moccur-buffers bufs helm-source-occur)
(helm-set-local-variable 'helm-multi-occur-buffer-list bufs)
(helm-set-local-variable
'helm-multi-occur-buffer-tick
(cl-loop for b in bufs
collect (buffer-chars-modified-tick (get-buffer b))))
(helm :sources 'helm-source-occur
:buffer "*helm occur*"
:history 'helm-grep-history
:input input
:truncate-lines t)))
(defun get-point-text ()
"Get 'interesting' text at point; either word, or region"
(if mark-active
(buffer-substring (mark) (point))
(thing-at-point 'symbol)))
(defun helm-occur-1 (initial-value)
"Preconfigured helm for Occur with initial input."
(helm-occur-from-point initial-value))
(defun bk-helm-occur ()
"Invoke helm-occur with initial input configured from text at point"
(interactive)
(helm-occur-1 (get-point-text)))
(global-set-key (kbd "M-s-o") 'bk-helm-occur)
primary it based on
#see https://news.ycombinator.com/item?id=6872508 but on last helm versions not work but fixed with my changes (just copy/paste from some internal helm modules)
Using capture templates like the one below, I can add entries to different headlines in a file. How can I manually enter a headline during capture, instead of setting up each headline to a key in the .emacs file like I am now doing?
(setq org-capture-templates
'(
("l" "Log" entry
(file+headline "c:/Org/log.org" "Log")
"\n\n** %?\n<%<%Y-%m-%d %a %T>>"
:empty-lines 1))
It looks like, in newer versions of org at least, that custom functions can be used in capture templates to do this.
Instead of:
entry
(file+headline "~/Work/work.org" "Refile")
You can use:
entry
(file+function "~/Work/work.org" function-finding-location)
Where 'function-finding-location' is a custom function you have written yourself, which could easily prompt you for a headline.
Or, you can go even farther, and define a custom function which will prompt for both file name and headline name (or anything else you can dream up):
entry
(function function-finding-location)
I don't really know enough elisp to write these functions myself, but this looks like the place to start. It'd be nice if someone else could offer up some code. The relevant documentation is here:
http://orgmode.org/manual/Template-elements.html
I wrote a function to be used with file+function which will prompt for a location on capture.
It uses the internal prompting function of org-refile so we get completions of headings in the prompt (with maxlevels overridden to 9). When the user enters an unknown heading, it creates it at the end of the file.
(defun org-ask-location ()
(let* ((org-refile-targets '((nil :maxlevel . 9)))
(hd (condition-case nil
(car (org-refile-get-location nil nil t t))
(error (car org-refile-history)))))
(goto-char (point-min))
(outline-next-heading)
(if (re-search-forward
(format org-complex-heading-regexp-format (regexp-quote hd))
nil t)
(goto-char (point-at-bol))
(goto-char (point-max))
(or (bolp) (insert "\n"))
(insert "* " hd "\n")))
(end-of-line))
In your case, you use it like this:
(setq org-capture-templates
'(("l" "Log" entry
(file+function "c:/Org/log.org" org-ask-location)
"\n\n** %?\n<%<%Y-%m-%d %a %T>>"
:empty-lines 1))
I don't believe you can have it prompt for the headline on capture. You can however refile from within the capture window which should result in the desired behaviour.
I would define a catch-all target headline/file so that if you forget you will always collect them in the same location and then just have to refile them once created. If you also set a category/tag on this headline you will be able to easily see the misfiled capture entry and refile it as desired. (Example below)
Then instead of finishing with C-c C-c choose to refile with C-c C-w and you will be asked to select the headline you want to send the new entry to.
The capture template I use for this catch all is as follows (adapted from Bernt Hansen's capture settings)
("i"
"Incidents"
entry
(file+headline "~/Work/work.org" "Refile")
"* TODO %^{Ticket} - %^{User}\nSCHEDULED: %^t DEADLINE: %^t\n:PROPERTIES:
\n:DATE: %^U\n:END:\n%^{MANAGER}p%^{HOSTNAME}p%^{LOCATION}p%^{TEL}p\n%c"
:empty-lines 1 :clock-in t :clock-resume t)
(Line breaks are added to avoid scrolling when reading here)
The heading is configured as follows
* Refile :refile:
:PROPERTIES:
:CATEGORY: Unsorted
:END:
With this I end up with all non-refiled tasks showing up as
Unsorted: Deadline: TODO <Headline> :refile::
I currently tend to use tags as reference if I'm waiting for coworkers/managers to deal with the ticket, or to remind me to speak to them about it when I see them so the tag at the end stands out clearly, as does Unsorted if I'm trying to remember what the issue is (since I simply have a case number and user name showing, details within the entry).
while capturing a note, after finishing writeup press C-u C-c C-w to refile under desired new headline.
you also need to set this variable
(setq org-refile-allow-creating-parent-nodes (quote confirm))
you can set it to t instead of confirm. But I like it be confirm because I dont often refile to new targets
When I use Emacs I want to be able to easily display and navigate through a list of files I worked on from not just the current session but from previous sessions. (BTW, running Emacs 22.2 on Windows)
From Joe Grossberg's blog (no longer available):
But if you're using GNU Emacs 21.2
(the latest version, which includes
this as part of the standard distro),
you can just put the following lines
into your .emacs file
;; recentf stuff
(require 'recentf)
(recentf-mode 1)
(setq recentf-max-menu-items 25)
(global-set-key "\C-x\ \C-r" 'recentf-open-files)
Then, when you launch emacs, hit
CTRL-X CTRL-R. It will show a list of
the recently-opened files in a buffer.
Move the cursor to a line and press
ENTER. That will open the file in
question, and move it to the top of
your recent-file list.
(Note: Emacs records file names.
Therefore, if you move or rename a
file outside of Emacs, it won't
automatically update the list. You'll
have to open the renamed file with the
normal CTRL-X CTRL-F method.)
Jayakrishnan Varnam has a page
including screenshots of how this
package works.
Note: You don't need the (require 'recentf) line.
Even if you don't have recentf turned on, Emacs is saving a list of files entered via the minibuffer in the variable file-name-history. Also, executing (savehist-mode 1) in your .emacs file makes that variable persist across invocations of Emacs.
So here's a little function that displays the files that actually exist from that list (anyone is welcome to use/build on this):
(defun dir-of-recent-files ()
"See the list of recently entered files in a Dired buffer."
(interactive)
(dired (cons
"*Recent Files*"
(seq-filter
'file-exists-p
(delete-dups
(mapcar (lambda (s) (string-trim-right s "/*"))
file-name-history)
))))
)
I find this quite useful and have it bound to one of those little special function keys on my desktop keyboard. (And so I have not seen the point of turning on recentf...)