ChatGPT解决这个技术问题 Extra ChatGPT

Re-open *scratch* buffer in Emacs?

If I accidentally closed the scratch buffer in Emacs, how do I create a new scratch buffer?


b
bignose

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


Note that there is something special about scratch, at least in GNU Emacs 21 and later: switching to a new scratch buffer will put it back into Lisp Interaction mode.
Just as a quick follow up to this, if your .emacs defines a different default scratch mode, this one will be the mode for the new scratch - not List Interaction mode.
e
elemakil

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.


When I try this advice from "ibuffer", the advice is ignored. But as best I can tell, "ibuffer" is using "kill-buffer". Can you help me?
Well, hitting "close buffer" in the graphical interface scratch is deleted. This works for C-x k only,
e
elemakil

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))             

S
Steven Huwig

C-x b *scratch* RET y RET with iswitchb-mode enabled.

Just C-x b *scratch* RET otherwise.


With default bindings, the 'y RET' is not needed and just inserts a 'y' and a newline into the newly created scratch buffer.
Ooops, maybe that's from iswitchb-mode. Sorry about that. On another topic, try out iswitchb-mode ;)
One should not, also, there's nothing special about the name scratch. One can use C-x b to create any number of "scratch" buffers, with arbitrary names.
There is something special about the name *scratch* (as noted in the accepted answer) -- if you create a buffer called *scratch* the major mode will be set according to the initial-major-mode variable (lisp-interaction-mode by default).
e
elemakil

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)
;;;----------------------------------------------------------------------

e
elemakil

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)

e
elemakil

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*")))

e
elemakil

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


How is this superior to simply switching to a new buffer (C-x b bufname RET)?
@bignose: I use ido-mode and usually have quite a few buffers open. Creating a new buffer using C-x b would be really tedious. I would have to come up with a unique name that doesn't match any of the currently present buffers.
C
CodyChan
(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.


n
nj35

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.


e
elemakil

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)))

l
lawlist

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) ))

A
Andreas Spindler

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.


Q
Qian

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))

p
petre

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


I
Ivan Sviatenko

C-xb and then type *scratch* ↩︎

to create a new buffer which is in lisp interaction mode also.