How do I get a warning before killing a temporary buffer in Emacs? - emacs

More than once I've lost work by accidentally killing a temporary buffer in Emacs. Can I set up Emacs to give me a warning when I kill a buffer not associated with a file?

Make a function that will ask you whether you're sure when the buffer has been edited and is not associated with a file. Then add that function to the list kill-buffer-query-functions.
Looking at the documentation for Buffer File Name you understand:
a buffer is not visiting a file if and only if the variable buffer-file-name is nil
Use that insight to write the function:
(defun maybe-kill-buffer ()
(if (and (not buffer-file-name)
(buffer-modified-p))
;; buffer is not visiting a file
(y-or-n-p "This buffer is not visiting a file but has been edited. Kill it anyway? ")
t))
And then add the function to the hook like so:
(add-to-list 'kill-buffer-query-functions 'maybe-kill-buffer)

(defun maybe-kill-buffer ()
(if (and (not buffer-file-name)
(buffer-modified-p))
;; buffer is not visiting a file
(y-or-n-p (format "Buffer %s has been edited. Kill it anyway? "
(buffer-name)))
t))
(add-to-list 'kill-buffer-query-functions 'maybe-kill-buffer)

Related

The function to show current file's full path in mini buffer

I need to get the full path of the file that I'm editing with emacs.
Is there a function for that?
If not, what would be the elisp function for getting that?
How can I copy the result (path name) to a clipboard so that I can reuse it?
I'm using Mac OS X and Aqumacs.
(setq filepath (get-fullpath-current-file)) ???
(copy-to-clipboard 'filepath) ???
ADDED
(defun show-file-name ()
"Show the full path file name in the minibuffer."
(interactive)
(message (buffer-file-name))
(kill-new (file-truename buffer-file-name))
)
(global-set-key "\C-cz" 'show-file-name)
Combining the two answers that I got, I could get what I want. Thanks for the answers. And some more questions.
What's for (file-truename)?
Can I copy the path name to System(OS)'s clipboard, not the kill ring so that I can use the info with the other apps?
It's the built-in function buffer-file-name that gives you the full path of your file.
The best thing to do is to have your emacs window to always show your system-name and the full path of the buffer you're currently editing :
(setq frame-title-format
(list (format "%s %%S: %%j " (system-name))
'(buffer-file-name "%f" (dired-directory dired-directory "%b"))))
You can also do something like this :
(defun show-file-name ()
"Show the full path file name in the minibuffer."
(interactive)
(message (buffer-file-name)))
(global-set-key [C-f1] 'show-file-name) ; Or any other key you want
To borrow from Jérôme Radix's answer, if you just want to quickly see the file path of the current buffer, you can do M-: buffer-file-name.
Alternately, type (buffer-file-name) in the buffer somewhere and run C-x C-e on the closing parenthesis (this will work in any mode, not just lisp-mode).
My trick is to do a C-x C-f like to open a file, it wil prefill the minibuff with the current file path, C-g to quit. Faster than M-: buffer-file-name but far far uglier than any other methods.
The direct implementation of what you want is:
(defun copy-full-path-to-kill-ring ()
"copy buffer's full path to kill ring"
(interactive)
(when buffer-file-name
(kill-new (file-truename buffer-file-name))))
That said, I find it incredibly useful to be able to get the full path of what is in the minibuffer, and this is what I use:
(define-key minibuffer-local-completion-map "\C-r" 'resolve-sym-link)
(defun resolve-sym-link ()
"Try to resolve symbolic links into true paths."
(interactive)
(beginning-of-line)
(let* ((file (buffer-substring (point)
(save-excursion (end-of-line) (point))))
(file-dir (file-name-directory file))
(file-true-dir (file-truename file-dir))
(file-name (file-name-nondirectory file)))
(delete-region (point) (save-excursion (end-of-line) (point)))
(insert (concat file-true-dir file-name))))
And then if I want it in the clipboard, I just kill the line (C-a C-k). But we could easily copy the truename to the clipboard in the above command, just change the last line to be:
(insert (kill-new (concat file-true-dir file-name)))))
The new part is the call to 'kill-new which puts the string in the kill ring.
No need for extra function, just
M-! pwd
C-x C-b shows a list of buffers and the file path for each buffer where applicable.
C-x C-d, also callable via M-x list-directory, will show you the directory for your current file, and you only need to hit the "Enter" key to clear the minibuffer. Additional details are available here.
I have the following code already in use for a long time.
It copies the full file path to the kill ring when I press the middle mouse button on the buffer name in the mode-line. It copies just the buffer name to the kill-ring when I press shift-mouse-2 on the buffer-name in the mode-line.
(defun copy-buffer-file-name (event &optional bufName)
"Copy buffer file name to kill ring.
If no file is associated with buffer just get buffer name.
"
(interactive "eP")
(save-selected-window
(message "bufName: %S" bufName)
(select-window (posn-window (event-start event)))
(let ((name (or (unless bufName (buffer-file-name)) (buffer-name))))
(message "Saved file name \"%s\" in killring." name)
(kill-new name)
name)))
(define-key mode-line-buffer-identification-keymap [mode-line mouse-2] 'copy-buffer-file-name)
(define-key mode-line-buffer-identification-keymap [mode-line S-mouse-2] '(lambda (e) (interactive "e") (copy-buffer-file-name e 't)))
C-u C-x C-b lists buffers currently visiting files.
Can I copy the path name to System(OS)'s clipboard, not the kill ring so that I can use the info with the other apps?
You can if you shell out to something like xclip (Linux), pbcopy (Mac), putclip (Cygwin).
I personally use wrapper scripts c and p for copy and paste respectively, the first reading from standard input, the latter writing to standard output. That way, this works on all my development platforms:
(shell-command (format "echo '%s' | c" buffer-file-name))
I find this more reliable and configurable than using the Emacs clipboard support. For example, my c command copies the input to all 3 clipboards on Linux (primary, secondary, clipboard), so I can paste with either Ctrl-V or middle click.
The simplest way and would be
(buffer-name)<(C-x)(C-e)> for the file name to appear in the echo area
(buffer-name)<(C-u)(C-x)(C-e)> would print the location <here>
Borrowing from Trey Jackson
I came up with this:
(defun buffer-kill-path ()
"copy buffer's full path to kill ring"
(interactive)
(kill-new (buffer-file-name)))
You can find more information on site
copy-buffer-file-name-as-kill from [0] does exactly what you need I think. It also has the option to copy just directory name, or just file name.
[0] http://www.emacswiki.org/emacs/download/buffer-extension.el
To do what the title says (show the current file path in the minibuffer) you can do this:
M-x buffer-file-name
To permanently show it in the mode-line, you can use this:
(setq-default mode-line-buffer-identification
(list 'buffer-file-name
(propertized-buffer-identification "%12f")
(propertized-buffer-identification "%12b")))
Or this (color + abbrev) :
(setq-default mode-line-buffer-identification
'((:eval
(list (propertize (abbreviate-file-name
(expand-file-name buffer-file-name))
'face 'font-lock-string-face)))))

Automatically closing the scratch buffer

What I must write in my .emacs file so that the *scratch* buffer is closed when I open Emacs?
(kill-buffer "*scratch*")
Not exactly the answer to your question, but you might like to know that you can choose to have a different buffer open on startup, or change the contents of the *scratch* buffer. For example:
;; Make *scratch* buffer blank.
(setq initial-scratch-message nil)
;; Make the buffer that opens on startup your init file ("~/.emacs" or
;; "~/.emacs.d/init.el").
(setq initial-buffer-choice user-init-file)
In the first example, the *scratch* buffer will be empty. In the second example, the *scratch* buffer will still exist, but user-init-file will be focused.
You can customize:
initial-buffer-choice
I set it to my homedir: "~/" to start in Dired mode.
I suspect from your question that you probably start emacs fairly often, perhaps even once for each file you want to edit. (If I'm wrong in this assumption, then the following comments don't apply to you.)
Emacs is designed to be started and then left running for weeks or months while you visit various files as you need to edit them. Emacs handles multiple files very well, so it's hardly even necessary to kill the associated buffers until you get 50 or 100 of them hanging around. I start emacs just after my window system starts, and it runs until my system shuts down or crashes. The initial scratch buffer is a non-problem in this mode, because I see it so infrequently.
I use this to kill the scratch buffer and open a new buffer in text mode called Untitled.
Found it on a newsgroup and modified it slightly.
(defun my-close-scratch ()
(kill-buffer "*scratch*")
(if (not (delq nil (mapcar 'buffer-file-name (buffer-list))))
(new-untitled-buffer)
))
(defun my-emacs-startup-hook ()
(my-close-scratch))
(add-hook 'emacs-startup-hook 'my-emacs-startup-hook)
(defun new-untitled-buffer ()
"Opens a new empty buffer."
(interactive)
(let ((buf (generate-new-buffer "Untitled")))
(switch-to-buffer buf)
(normal-mode)
(setq buffer-offer-save t))
(add-hook 'kill-buffer-query-functions
'ask-to-save-modified nil t)
)
To close Untitled when opening files from filemanager when emacs is not open I use this:
(defun my-close-untitled ()
(if (get-buffer "Untitled")
(kill-buffers-by-name "Untitled")))
(add-hook 'find-file-hook 'my-close-untitled)
The proper way is to add inhibit-startup-screen to the custom-set-variables section of your .emacs file.
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(inhibit-startup-screen t)
)

File path to clipboard in Emacs

What is the most simple way to send current full file name with file path to clipboard?
What I am using now is messages buffer: I copy file name that appears there after saving a file. But, I suppose, there should be much more simple way.
Why no one tell the simple solution.
Just go to your dired buffer then press 0 w or C-u 0 w.
This will call dired-copy-filename-as-kill which gives you full path of a file. If you want current dir, just delete the file at the end of it or you can use the function below, then bind it to any key you like.
(defun my/dired-copy-dirname-as-kill ()
"Copy the current directory into the kill ring."
(interactive)
(kill-new default-directory))
PS: personally I go to current directory from file buffer using dired-jump
I use this:
(defun my-put-file-name-on-clipboard ()
"Put the current file name on the clipboard"
(interactive)
(let ((filename (if (equal major-mode 'dired-mode)
default-directory
(buffer-file-name))))
(when filename
(with-temp-buffer
(insert filename)
(clipboard-kill-region (point-min) (point-max)))
(message filename))))
In Emacs Prelude I use:
(defun prelude-copy-file-name-to-clipboard ()
"Copy the current buffer file name to the clipboard."
(interactive)
(let ((filename (if (equal major-mode 'dired-mode)
default-directory
(buffer-file-name))))
(when filename
(kill-new filename)
(message "Copied buffer file name '%s' to the clipboard." filename))))
If you want to write the name/path of the current buffer you can type C-u M-: and then either (buffer-file-name) - for the full path - or (buffer-name) for the buffer name.
That is:
M-: + ellisp expression evaluates an ellisp expression in the mini-buffer
C-u write the output to the current buffer
Does not exactly answer to the question but could be useful if someone use this or other function sporadically, and prefers to not initialize the function at every startup.
In the Spacemacs distribution, you can press Spacefyy to display the buffer name in the minibuffer and copy it to the kill ring.
The function spacemacs/show-and-copy-buffer-filename seems to originate from this blog post: Emacs: Show Buffer File Name.
(defun camdez/show-buffer-file-name ()
"Show the full path to the current file in the minibuffer."
(interactive)
(let ((file-name (buffer-file-name)))
(if file-name
(progn
(message file-name)
(kill-new file-name))
(error "Buffer not visiting a file"))))
There's a buffer-extension - and it has copy-buffer-file-name-as-kill function. It even asks You what to copy: name, full name or a directory name.
Edit:
I use modified version of copy-buffer-file-name-as-kill from buffer-extension.el:
(defun copy-buffer-file-name-as-kill (choice)
"Copyies the buffer {name/mode}, file {name/full path/directory} to the kill-ring."
(interactive "cCopy (b) buffer name, (m) buffer major mode, (f) full buffer-file path, (d) buffer-file directory, (n) buffer-file basename")
(let ((new-kill-string)
(name (if (eq major-mode 'dired-mode)
(dired-get-filename)
(or (buffer-file-name) ""))))
(cond ((eq choice ?f)
(setq new-kill-string name))
((eq choice ?d)
(setq new-kill-string (file-name-directory name)))
((eq choice ?n)
(setq new-kill-string (file-name-nondirectory name)))
((eq choice ?b)
(setq new-kill-string (buffer-name)))
((eq choice ?m)
(setq new-kill-string (format "%s" major-mode)))
(t (message "Quit")))
(when new-kill-string
(message "%s copied" new-kill-string)
(kill-new new-kill-string))))
If you use Doom Emacs, it can be done with SPC f y.
To paste the current file path in the buffer, the most simple way I see is to do: C-u M-! pwd (this might not work on Windows systems though).
Alternatively, you can use C-x C-b to show the file paths of all opened buffers.
This is what has worked for me on MacOS 10.15.7, GNU Emacs 27.1
(defun copy-current-buffer-file-name ()
(interactive)
(shell-command (concat "echo " (buffer-file-name) " | pbcopy")))
set keybinding to "C-x M-f":
(global-set-key (kbd "C-x M-f") 'copy-current-buffer-file-name)
FYI: For a real beginner reading this, you need to add those lines to your init.el file.
Lots of good answers here, though I think for the "most simple way", as described in the question, there's room for improvement. Here's what I came up with (with thanks to other answers for the bits and pieces):
M-: (kill-new (buffer-file-name)) RET
This does precisely what you asked for -- takes the filename of the current buffer, and puts it in the "kill ring" and, depending on your settings, also the system clipboard. (See emacswiki/CopyAndPaste for more details on that part.)
If you want to do this regularly, then setting up a function like listed in the other answers, and binding it to an available key sequence, would make it easier to do frequently. But the above works with no prior setup, which I'm interpreting to be more "simple".

Emacs - Can't get buffer-offer-save working

I would like to have Emacs ask me whether I want to save a modified buffer, when that buffer is not associated with a file. To open a new buffer (not visiting a file) I have the following function in my .emacs file:
;; Creates a new empty buffer
(defun new-empty-buffer ()
"Opens a new empty buffer."
(interactive)
(let ((buf (generate-new-buffer "untitled")))
(switch-to-buffer buf)
(funcall (and default-major-mode))
(setq buffer-offer-save t)))
I thought setting "buffer-offer-save" to something not nil would made the trick. But whenever I kill the buffer with "kill-this-buffer", it gets instantly killed without asking anything.
This happens on GNU Emacs 23.1.1
Any ideas?
Thanks,
W
Edited to add use of buffers-offer-save. Note: the variable buffer-offer-save is only used upon exiting Emacs.
You can start with this code and customize it to what you want:
(add-to-list 'kill-buffer-query-functions 'ask-me-first)
(defun ask-me-first ()
"prompt when killing a buffer"
(if (or buffer-offer-save
(eq this-command 'kill-this-buffer)
(and (buffer-modified-p) (not (buffer-file-name))))
(y-or-n-p (format "Do you want to kill %s without saving? " (buffer-name)))
t))
Upon further reflection, that is a bit heavy-handed because you get prompted for all buffers that get killed, and there are often lots of temporary buffers that Emacs uses. If you just want to be prompted when you try to interactively kill a buffer (that isn't associated with a file).
You can use this advice which only prompts you when you're interactively trying to kill a buffer:
(defadvice kill-buffer (around kill-buffer-ask-first activate)
"if called interactively, prompt before killing"
(if (and (or buffer-offer-save (interactive-p))
(buffer-modified-p)
(not (buffer-file-name)))
(let ((answ (completing-read
(format "Buffer '%s' modified and not associated with a file, what do you want to do? (k)ill (s)ave (a)bort? " (buffer-name))
'("k" "s" "a")
nil
t)))
(when (cond ((string-match answ "k")
;; kill
t)
((string-match answ "s")
;; write then kill
(call-interactively 'write-file)
t)
(nil))
ad-do-it)
t)
;; not prompting, just do it
ad-do-it))
Modifying 'new-empty-buffer seems to make it work as I intended with Trey's defadvice.
;; Creates a new empty buffer
(defun new-empty-buffer ()
"Opens a new empty buffer."
(interactive)
(let ((buf (generate-new-buffer "untitled")))
(switch-to-buffer buf)
(funcall (and default-major-mode))
(put 'buffer-offer-save 'permanent-local t)
(setq buffer-offer-save t)))
This makes buffer-offer-save permanent local in our new buffer, so it won't get killed with the rest of the local variables when switching major modes.
buffer-offer-save asking on exiting Emacs but not on closing a buffer manually doesn't make sense, so why not “enlarge” its responsibilities?
(defadvice kill-buffer (around kill-buffer-ask activate)
"If `buffer-offer-save' is non-nil and a buffer is modified,
prompt before closing."
(if (and buffer-offer-save (buffer-modified-p))
(when (yes-or-no-p "The document isn't saved. Quit? ")
ad-do-it)
ad-do-it))
It will not prompt if untitled buffer is newly created. It will not prompt if you use kill-buffer from Elisp. It will not prompt on Emacs system buffers like *Messages*. But it will prompt if you created an empty buffer and wrote something in it.
See also my answer on creating an empty 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.