Close all buffers besides the current one in Emacs - emacs

How do I close all but the current buffer in Emacs? Similar to "Close other tabs" feature in modern web browsers?

For a more manual approach, you can list all buffers with C-x C-b, mark buffers in the list for deletion with d, and then use x to remove them.
I also recommend replacing list-buffers with the more advanced ibuffer: (global-set-key (kbd "C-x C-b") 'ibuffer). The above will work with ibuffer, but you could also do this:
m (mark the buffer you want to keep)
t (toggle marks)
D (kill all marked buffers)
I also use this snippet from the Emacs Wiki, which would further streamline this manual approach:
;; Ensure ibuffer opens with point at the current buffer's entry.
(defadvice ibuffer
(around ibuffer-point-to-most-recent) ()
"Open ibuffer with cursor pointed to most recent buffer name."
(let ((recent-buffer-name (buffer-name)))
ad-do-it
(ibuffer-jump-to-buffer recent-buffer-name)))
(ad-activate 'ibuffer)

From EmacsWiki: Killing Buffers:
(defun kill-other-buffers ()
"Kill all other buffers."
(interactive)
(mapc 'kill-buffer
(delq (current-buffer)
(remove-if-not 'buffer-file-name (buffer-list)))))
Edit: updated with feedback from Gilles

There isn't a way directly in emacs to do this.
You could write a function to do this. The following will close all the buffers:
(defun close-all-buffers ()
(interactive)
(mapc 'kill-buffer (buffer-list)))

There is a built in command m-x kill-some-buffers (I'm using 24.3.50) In my nextstep gui (not tried in a terminal but sure it's similar) you can then approve which buffers to kill.

(defun only-current-buffer ()
(interactive)
(let ((tobe-killed (cdr (buffer-list (current-buffer)))))
(while tobe-killed
(kill-buffer (car tobe-killed))
(setq tobe-killed (cdr tobe-killed)))))
It works as you expected.
And after reading #Starkey's answer, I think this will be better:
(defun only-current-buffer ()
(interactive)
(mapc 'kill-buffer (cdr (buffer-list (current-buffer)))))
(buffer-list (current-buffer)) will return a list that contains all the existing buffers, with the current buffer at the head of the list.
This is my first answer on StackOverflow. Hope it helps :)

I found this solution to be the simplest one. This deletes every buffer except the current one. You have to add this code to your .emacs file
(defun kill-other-buffers ()
"Kill all other buffers."
(interactive)
(mapc 'kill-buffer (delq (current-buffer) (buffer-list))))
Of course, then you use it with M-x kill-other-buffers RET or you paste the following code in the .emacs file too and then just press C-xC-b
(global-set-key (kbd "C-x C-b") 'kill-other-buffers)

You can like this one as well - kill all buffers except current one, *Messages* and *scratch* (which are handy to have, I call them "toolkit"), close redundant windows as well, living you which one window which current buffer.
(defun my/kill-all-buffers-except-toolbox ()
"Kill all buffers except current one and toolkit (*Messages*, *scratch*). Close other windows."
(interactive)
(mapc 'kill-buffer (remove-if
(lambda (x)
(or
(eq x (current-buffer))
(member (buffer-name x) '("*Messages*" "*scratch*"))))
(buffer-list)))
(delete-other-windows))

I've use crux-kill-other-buffers for some months.
But I want dired buffers get deleted too. #Euge's and #wenjun.yan's answers solve this. But it will delete special buffers (e.g *git-credential-cache--daemon*, *scratch*, helm operation, and etc). So I came up with this (current) solution.
(defun aza-kill-other-buffers ()
"Kill all buffers but current buffer and special buffers"
(interactive)
(dolist (buffer (delq (current-buffer) (buffer-list)))
(let ((name (buffer-name buffer)))
(when (and name (not (string-equal name ""))
(/= (aref name 0) ?\s)
(string-match "^[^\*]" name))
(funcall 'kill-buffer buffer)))))
Inspired from kill-matching-buffers. You can add more condition on other buffer-name to exclude, if you want to.
Hope it helps :)

I've used one of the solutions in this list for years, but now I have a new one of my own.
(defun kill-all-file-buffers ()
"Kills all buffers that are open to files. Does not kill
modified buffers or special buffers."
(interactive)
(mapc 'kill-buffer (cl-loop for buffer being the buffers
when (and (buffer-file-name buffer)
(not (buffer-modified-p buffer)))
unless (eq buffer (current-buffer))
collect buffer)))
cl-loop has buffers built in as a collection that you can iterate over. It gives you a chance to parse out anything you don't want to close. Here, I've made sure that it doesn't close anything you've modified, and it uses buffer-file-name instead of just buffer-name so it doesn't kill special buffers. I also added an 'unless' to take out the current buffer (though you could obviously add it to the 'when', I just thought this was clearer).
But for an even more generic solution, we can define this as a macro, and pass in a function that will apply to all these buffers.
(defmacro operate-on-file-buffers (func)
"Takes any function that takes a single buffer as an argument
and applies that to all open file buffers that haven't been
modified, and aren't the current one."
`(mapc ,func (cl-loop for buffer being the buffers
when (and (buffer-file-name buffer)
(not (buffer-modified-p buffer)))
unless (eq buffer (current-buffer))
collect buffer)))
Now if you want to kill all buffers that match this, you can call it like this
(operate-on-file-buffers 'kill-buffer)

This is what you want:
C-x 1
source: https://blasphemousbits.wordpress.com/2007/05/04/learning-emacs-part-4-buffers-windows-and-frames/

Related

Is there emacs capability for visiting last edits?

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

In emacs, how do I save without running save hooks?

I have various things set up in my 'before-save-hook. For example, I run 'delete-trailing-whitespace. This is what I want in almost all occasions.
But sometimes, I'm working on files that are shared with other people, and the file already has a bunch of trailing whitespace. If I save the file, I'll get a big diff that's pretty confusing, as my change is buried in dozens or hundreds of meaningless changes. Yes, everyone could just tell their diff tool to not show whitespace changes, but that's something that everyone has to do every time they look at the diff. I'd rather not even have the whitespace change.
Is there anything I can do to save the file without the whitespace changes, short of starting a new instance of Emacs with no init.el file, or with a modified init.el that doesn't have the hook?
Here is how I save without triggering delete-trailing-whitespace:
C-x C-q C-x C-s C-x C-q: read-only, save, revert read-only
A simpler solution I came up with is that my fundamental-mode has no hooks installed, because I want it to be as plain as possible. Thus if I want to save a file without running hooks, I temporarily switch to fundamental-mode.
Based on a comment discussion with #Stefan, here are two possible (untested) solutions:
Use let:
(defun save-buffer-without-dtw ()
(interactive)
(let ((b (current-buffer))) ; memorize the buffer
(with-temp-buffer ; new temp buffer to bind the global value of before-save-hook
(let ((before-save-hook (remove 'delete-trailing-whitespace before-save-hook)))
(with-current-buffer b ; go back to the current buffer, before-save-hook is now buffer-local
(let ((before-save-hook (remove 'delete-trailing-whitespace before-save-hook)))
(save-buffer)))))))
Use unwind-protect:
(defun save-buffer-without-dtw ()
(interactive)
(let ((restore-global
(memq 'delete-trailing-whitespace (default-value before-save-hook)))
(restore-local
(and (local-variable-p 'before-save-hook)
(memq 'delete-trailing-whitespace before-save-hook))))
(unwind-protect
(progn
(when restore-global
(remove-hook 'before-save-hook 'delete-trailing-whitespace))
(when restore-local
(remove-hook 'before-save-hook 'delete-trailing-whitespace t))
(save-buffer))
(when restore-global
(add-hook 'before-save-hook 'delete-trailing-whitespace))
(when restore-local
(add-hook 'before-save-hook 'delete-trailing-whitespace nil t)))))
The problem with the second solution is that the order of functions in the before-save-hook may change.
Here's another solution:
(defvar my-inhibit-dtw nil)
(defun my-delete-trailing-whitespace ()
(unless my-inhibit-dtw (delete-trailing-whitespace)))
(add-hook 'before-save-hook 'my-delete-trailing-whitespace)
and then
(defun my-inhibit-dtw ()
(interactive)
(set (make-local-variable 'my-inhibit-dtw) t))
so you can M-x my-inhibit-dtw RET in the buffers where you don't want to trim whitespace.
I wrote a command inspired by Nicholas Douma's solution.
(defun olav-save-buffer-as-is ()
"Save file \"as is\", that is in read-only-mode."
(interactive)
(if buffer-read-only
(save-buffer)
(read-only-mode 1)
(save-buffer)
(read-only-mode 0)))
What we need to do is remove 'delete-trailing-whitespace from before-save-hook, save the buffer, then add it back.
This code will do that, but only remove and add it if it's there to begin with.
;; save the buffer, removing and readding the 'delete-trailing-whitespace function
;; to 'before-save-hook if it's there
(defun save-buffer-no-delete-trailing-whitespace ()
(interactive)
(let ((normally-should-delete-trailing-whitespace (memq 'delete-trailing-whitespace before-save-hook)))
(when normally-should-delete-trailing-whitespace
(remove-hook 'before-save-hook 'delete-trailing-whitespace))
(save-buffer)
(when normally-should-delete-trailing-whitespace
(add-hook 'before-save-hook 'delete-trailing-whitespace))))
(global-set-key (kbd "C-c C-s") 'save-buffer-no-delete-trailing-whitespace)
It also binds the command to (kbd C-c C-s), for convenience.

Show all open buffers in Emacs

In emacs, is there an M-x command or key combo to render all current open buffers into different windows?
For clarity, let's suppose I have four open buffers, and I am only seeing one currently being displayed, and I would like in one step to show each buffer in one quadrant.
I recommend ibuffer. M-x ibuffer is probably what you want. Here's my ibuffer configuration:
;; *Messages* is so annoying. Also, I really like ibuffer
(require 'ibuf-ext)
(add-to-list 'ibuffer-never-show-predicates "^\\*Messages")
(add-to-list 'ibuffer-never-show-predicates "^\\*Completions")
(global-set-key (kbd "C-b") 'ibuffer)
(kill-buffer "*scratch*")
('ibuffer)
(switch-to-buffer "*Ibuffer*")
You will be able to start with the following code if there is not an already-known way to do it:
(defun buffer-in-window-list ()
(let (buffers)
(walk-windows (lambda (window) (push (window-buffer window) buffers)) t t)
buffers))
(defun display-all-buffers ()
(interactive)
(let (buffers-in-window (buffer-in-window-list))
(dolist (buffer (buffer-list))
(when (and (not (string-match "\\`[[:space:]]*\\*" (buffer-name buffer)))
(not (memq buffer buffers-in-window)))
(set-window-buffer (split-window (get-largest-window)) buffer)))
(balance-windows)))
The display-all-buffers command opens a new window for each buffer that is not currently displayed anywhere (including other frames). For usability, it ignores buffers whose names start with * (optionally, prefixed with whitespace characters) because they are usually for internal use only.
Note that Emacs does not allow a user to make too small a window. So, when there are too many buffers to display, the command will display as many buffers as possible in order of most recent display or selection and signal an error.

.emacs.desktop file destroyed by custom function

I use the Emacs desktop module to save my open buffers between sessions. However I found that this accumulates more buffers than I want, so I wrote a small function to clean up the buffer list immediately before saving to the desktop file. This works as expected, but for strange reasons the .emacs.desktop gets scrambled occasionally, i.e. it contains a part of another buffer at its start, then the intended contents and then the result of the other buffer. I don't have the slightest idea, why this happens. Here is an excerpt from my .emacs file:
(defun kill-old-buffers ()
"Kill buffers from end of buffer list (not used recently) until no more than 50 buffers are left. Remove temporary buffers first"
(interactive)
(let* (desktop-buffer (current-buffer))
(dolist (buffer (buffer-list))
(if (or (string-match "^\*" (buffer-name buffer)) (string-match "\.hpp$" (buffer-name buffer)))
(kill-buffer buffer)
)
)
(setq all-buffers (reverse (buffer-list)))
(while (> (safe-length all-buffers) 50)
(setq buffer (pop all-buffers))
(if (not (string-equal (buffer-name buffer) (buffer-name (current-buffer))))
(kill-buffer buffer)
)
)
(switch-to-buffer desktop-buffer)
))
;; Kill old rarely-used buffers before saving
(add-hook 'desktop-save-hook
'(lambda () (kill-old-buffers)))
Any help would be appreciated.
I'm not sure if your function is really the cause of your problem. If it should be the case, the wrong usage of the let* that scottfrazer pointed out might be the cause. But you don't even need that let* (and switch-to-buffer) at all, because
what you're trying to do is better done with Emacs' built in save-excursion, and
you aren't actually switching the buffer ever.
OTOH, you should have used let instead of the setqs in the lower half of your function, because setq will otherwise change a variable from an enclosing lexical scope. In this case you might very well have stomped over a buffer variable from the function that's executing the desktop-save-hook which is another potential cause of your problem.
But you don't need those lets either because you can do the second loop with another dolist. You can get rid of those first 50 buffers that you don't want to loop over with nthcdr.
Here's my improved version of kill-old-buffers:
(defun kill-old-buffers ()
"Kill buffers from end of buffer list (not used recently) until
no more than 50 buffers are left. Remove temporary buffers first."
(interactive)
(save-excursion
(dolist (buffer (buffer-list))
(if (or (string-match "^\*" (buffer-name buffer))
(string-match "\.hpp$" (buffer-name buffer)))
(kill-buffer buffer)))
(dolist (buffer (reverse (nthcdr 50 (buffer-list))))
(unless (eq buffer (current-buffer))
(kill-buffer buffer)))))
It may not fix all your problems, but for starters you need another set of parens around the variable in your let* statement
(let* ((desktop-buffer (current-buffer)))

Re-open *scratch* buffer in Emacs?

If I accidentally closed the scratch buffer in Emacs, how do I create a new scratch buffer?
GNU Emacs default bindings:
C-xb *scratch* RET
or, more verbosely
M-x switch-to-buffer *scratch* RET
The *scratch* buffer is the buffer selected upon startup, and has the major mode Lisp Interaction. Note: the mode for the *scratch* buffer is controlled by the variable initial-major-mode.
In general you can create as many "scratch" buffers as you want, and name them however you choose.
C-xb NAME RET
switches to a buffer NAME, creating it if it doesn't exist. A new buffer is not associated with a file on disk until you use C-xC-w (or M-x write-file RET) to choose a file where it should be saved.
M-x text-mode RET
changes the current buffer's major mode to Text mode. To find all the modes available (that is, without requiring any new packages), you can get a list by typing:
M-x apropos-command -mode$ RET
I add following in my .emacs:
;; bury *scratch* buffer instead of kill it
(defadvice kill-buffer (around kill-buffer-around-advice activate)
(let ((buffer-to-kill (ad-get-arg 0)))
(if (equal buffer-to-kill "*scratch*")
(bury-buffer)
ad-do-it)))
If I don't want to see scratch buffer I press C-x C-k , but it doesn't kill it, just place in the end of buffer list, so then I need it next time I don't have to create new one.
There are a whole bunch of tips on this EmacsWiki page.
Here's the first one:
A very simple function to recreate the scratch buffer:
(defun create-scratch-buffer nil
"create a scratch buffer"
(interactive)
(switch-to-buffer (get-buffer-create "*scratch*"))
(lisp-interaction-mode))
C-x b *scratch* RET y RET with iswitchb-mode enabled.
Just C-x b *scratch* RET otherwise.
I found this years ago when I first started using emacs; I have no idea where now but it has always had a home in my personal .el files. It does pop up in google searches.
;;; Prevent killing the *scratch* buffer -- source forgotten
;;;----------------------------------------------------------------------
;;; Make the *scratch* buffer behave like "The thing your aunt gave you,
;;; which you don't know what is."
(save-excursion
(set-buffer (get-buffer-create "*scratch*"))
(make-local-variable 'kill-buffer-query-functions)
(add-hook 'kill-buffer-query-functions 'kill-scratch-buffer))
(defun kill-scratch-buffer ()
;; The next line is just in case someone calls this manually
(set-buffer (get-buffer-create "*scratch*"))
;; Kill the current (*scratch*) buffer
(remove-hook 'kill-buffer-query-functions 'kill-scratch-buffer)
(kill-buffer (current-buffer))
;; Make a brand new *scratch* buffer
(set-buffer (get-buffer-create "*scratch*"))
(lisp-interaction-mode)
(make-local-variable 'kill-buffer-query-functions)
(add-hook 'kill-buffer-query-functions 'kill-scratch-buffer)
;; Since we killed it, don't let caller do that.
nil)
;;;----------------------------------------------------------------------
Like the docstring says, this function will:
Switch to the scratch buffer. If the buffer doesn't exist create it and write the initial message into it."
This will bring a new scratch buffer up which looks like the initial scratch buffer.
(defun switch-buffer-scratch ()
"Switch to the scratch buffer. If the buffer doesn't exist,
create it and write the initial message into it."
(interactive)
(let* ((scratch-buffer-name "*scratch*")
(scratch-buffer (get-buffer scratch-buffer-name)))
(unless scratch-buffer
(setq scratch-buffer (get-buffer-create scratch-buffer-name))
(with-current-buffer scratch-buffer
(lisp-interaction-mode)
(insert initial-scratch-message)))
(switch-to-buffer scratch-buffer)))
(global-set-key "\C-cbs" 'switch-buffer-scratch)
I used to use dwj's solution, and I was quite happy about it, until the day I realized that it failed when you actually rename the scratch buffer (for example by saving it).
Then I adopted this, which works well for me :
(run-with-idle-timer 1 t
'(lambda () (get-buffer-create "*scratch*")))
I have scratch as an interactive command for opening a new scratch buffer (I like to have several):
(defun scratch ()
"create a new scratch buffer to work in. (could be *scratch* - *scratchX*)"
(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))
(if (= n 1) initial-major-mode))) ; 1, because n was incremented
adopted from: http://everything2.com/index.pl?node_id=1038451
(global-set-key (kbd "C-x M-z")
'(lambda ()
(interactive)
(switch-to-buffer "*scratch*")))
This will not only quickly switch to *scratch* buffer(since I do this frequently), but recreate a *scratch* buffer and enable lisp-interaction-mode automatically if you kill it accidentally. Change the binding as you like.
Just to note emacs package unkillable-scratch in MELPA will do this. There is also scratch-persist that will automatically save and restore the buffer between sessions.
This is what I use - I have this bound to a convenient keystroke. It sends you to the *scratch* buffer, regardless of whether or not it already exists, and sets it to be in lisp-interaction-mode
(defun eme-goto-scratch ()
"this sends you to the scratch buffer"
(interactive)
(let ((eme-scratch-buffer (get-buffer-create "*scratch*")))
(switch-to-buffer eme-scratch-buffer)
(lisp-interaction-mode)))
I prefer to have my scratch buffer be an actual file that is automatically saved, and reopening it is as simple as opening a file. On startup, I kill the default and find my own like this.
(add-hook 'emacs-startup-hook
(lambda ()
(kill-buffer "*scratch*")
(find-file "/Users/HOME/Desktop/.scratch")))
I have a custom kill-buffer function that does essentially the same thing -- reopens my personal scratch saved file and kills the default scratch if I killed the last visible buffer.
I customized a few of the desktop.el functions to load after (kill-buffer "*scratch*") and (find-file "/Users/HOME/Desktop/.scratch") so that the file last visible on exiting Emacs doesn't get buried by the default scratch or buried by my custom scratch when launching Emacs.
I enjoy using auto-save-buffers-enhanced, which automatically saves any file extension that is not specifically excluded:
https://github.com/kentaro/auto-save-buffers-enhanced/blob/master/auto-save-buffers-enhanced.el
(require 'auto-save-buffers-enhanced)
(auto-save-buffers-enhanced t)
(setq auto-save-buffers-enhanced-save-scratch-buffer-to-file-p 1)
(setq auto-save-buffers-enhanced-exclude-regexps '("\\.txt" "\\.el" "\\.tex"))
I use a slight variation of the function by #paprika when I want to create a no-file visiting buffer:
(defun lawlist-new-buffer ()
"Create a new buffer -- \*lawlist\*"
(interactive)
(let* (
(n 0)
bufname)
(catch 'done
(while t
(setq bufname (concat "*lawlist"
(if (= n 0) "" (int-to-string n))
"*"))
(setq n (1+ n))
(if (not (get-buffer bufname))
(throw 'done nil)) ))
(switch-to-buffer (get-buffer-create bufname))
(text-mode) ))
I have combined the solutions posted so far into one function:
(defun --scratch-buffer(&optional reset)
"Get the *scratch* buffer object.
Make new scratch buffer unless it exists.
If RESET is non-nil arrange it that it can't be killed."
(let ((R (get-buffer "*scratch*")))
(unless R
(message "Creating new *scratch* buffer")
(setq R (get-buffer-create "*scratch*") reset t))
(when reset
(save-excursion
(set-buffer R)
(lisp-interaction-mode)
(make-local-variable 'kill-buffer-query-functions)
(add-hook 'kill-buffer-query-functions '(lambda()(bury-buffer) nil)
)))
R))
To apply this function in your .emacs use:
(--scratch-buffer t)
(run-with-idle-timer 3 t '--scratch-buffer)
This will make the scratch buffer indestructible in the first place, and if saved it will be recreated. Additionally we can use a shortcut function scratch to bring up the buffer quickly:
(defun scratch()
"Switch to *scratch*. With prefix-arg delete its contents."
(interactive)
(switch-to-buffer (--scratch-buffer))
(if current-prefix-arg
(delete-region (point-min) (point-max))
(goto-char (point-max))))
In the past it has proven useful to know the original startup-directory from which Emacs was started. This is either the value of desktop-dirname or the default-directory local variable of the scratch-buffer:
(defvar --scratch-directory
(save-excursion (set-buffer "*scratch*") default-directory)
"The `default-directory' local variable of the *scratch* buffer.")
(defconst --no-desktop (member "--no-desktop" command-line-args)
"True when no desktop file is loaded (--no-desktop command-line switch set).")
(defun --startup-directory ()
"Return directory from which Emacs was started: `desktop-dirname' or the `--scratch-directory'.
Note also `default-minibuffer-frame'."
(if (and (not --no-desktop) desktop-dirname)
desktop-dirname
--scratch-directory))
So --startup-directory will always return the base directory of your makefile, TODO-file etc. In case there is no desktop (--no-desktop commandline-switch or no desktop-file) the --scratch-directory variable will hold directory Emacs was once started under.
find answer in EmacsWiki: http://www.emacswiki.org/emacs/RecreateScratchBuffer
(defun create-scratch-buffer nil
"create a scratch buffer"
(interactive)
(switch-to-buffer (get-buffer-create "*scratch*"))
(lisp-interaction-mode))
To add to the accepted answer, if you have ILO mode on (and it is autocompleting after C-x b, thus not letting you write *scratch*), then try:
C-xb C-b*scratch* RET
C-x b C-b *scratch* RET
C-xb and then type *scratch* ↩︎
to create a new buffer which is in lisp interaction mode also.