在Emacs中重新打开*scratch*缓冲区?

175
如果我意外关闭了Emacs中的scratch缓冲区,那么如何创建一个新的scratch缓冲区?
16个回答

209

GNU Emacs默认绑定:

C-xb *scratch* RET

或者更详细地说:

M-x switch-to-buffer *scratch* RET

*scratch*缓冲区是启动时选择的缓冲区,并具有主模式Lisp交互。注意:缓冲区*scratch*的模式由变量initial-major-mode控制。

通常情况下,您可以创建任意数量的“scratch”缓冲区,并按照自己的选择进行命名。

C-xb NAME RET

切换到缓冲区NAME,如果不存在则创建它。新缓冲区在使用C-xC-w(或M-x write-file RET)选择保存文件的位置之前不会与磁盘上的文件关联。

M-x text-mode RET

将当前缓冲区的主模式更改为文本模式。要查找所有可用的模式(即,不需要任何新包),可以键入:

M-x apropos-command -mode$ RET


8
请注意,在GNU Emacs 21及更高版本中,scratch有一些特殊的地方:切换到一个新的scratch缓冲区将会使它回到Lisp交互模式。 - Peter S. Housel
作为对此的快速跟进,如果您的.emacs定义了不同的默认scratch模式,则该模式将成为新scratch的模式,而不是列表交互模式。 - ocodo

23
我在我的 .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)))

如果我不想看到scratch缓冲区,我按C-x C-k键,但它并没有被删除,只是放在了缓冲区列表的末尾,这样下次我需要时就不必创建新的缓冲区。


当我尝试使用“ibuffer”中的建议时,该建议被忽略了。但据我所知,“ibuffer”正在使用“kill-buffer”。你能帮我吗? - A.Ellett
在图形界面中点击“关闭缓冲区”将会删除scratch。这仅适用于C-x k。 - Maurizio Loreti

15

这个EmacsWiki页面上有许多关于此问题的技巧。

以下是第一个技巧:

重新创建scratch buffer的非常简单的函数:

(defun create-scratch-buffer nil
   "create a scratch buffer"
   (interactive)
   (switch-to-buffer (get-buffer-create "*scratch*"))
   (lisp-interaction-mode))             

9

启用iswitchb模式后,使用C-x b *scratch* RET y RET。

否则,只需使用C-x b *scratch* RET。


使用默认绑定,'y RET' 不需要,只会在新创建的 scratch 缓冲区中插入一个 'y' 和一个换行符。 - Trey Jackson
抱歉,可能是来自iswitchb-mode。对此感到抱歉。另外,试试iswitchb-mode吧 ;) - Steven Huwig
一个人不应该认为,而且“scratch”这个名字也没有什么特别的。可以使用C-x b创建任意数量的“scratch”缓冲区,并赋予任意名称。 - Chris Conway
1
关于名称 *scratch* 有一些特殊之处(如被接受的答案所指出)-- 如果你创建一个名为 *scratch* 的缓冲区,主模式将根据 initial-major-mode 变量进行设置(默认为 lisp-interaction-mode)。 - phils

4

我在几年前开始使用emacs时发现了这个内容;我不知道它现在在哪里,但它一直有一个家在我的个人.el文件中。它会在谷歌搜索结果中出现。

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

3
(global-set-key (kbd "C-x M-z")
                '(lambda ()
                   (interactive)
                   (switch-to-buffer "*scratch*")))

我经常使用这个快捷键,它不仅能够快速切换到 *scratch* 缓冲区,还可以在意外删除时重新创建 *scratch* 缓冲区并自动启用 lisp-interaction-mode。您可以根据需要更改绑定。


3

请注意,MELPA中的emacs包unkillable-scratch可以实现此功能。还有一个scratch-persist会在会话之间自动保存和恢复缓冲区。


3

如文档字符串所述,该函数将执行以下操作:

切换到“scratch”缓冲区。如果缓冲区不存在,则创建它并将初始消息写入其中。

这将带来一个新的“scratch”缓冲区,它看起来像初始的“scratch”缓冲区。

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

3

我将scratch作为交互式命令,用于打开新的空白缓冲区(我喜欢有几个):

(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

引自:http://everything2.com/index.pl?node_id=1038451

技术术语通常很难理解,所以要在翻译时注意使之变得通俗易懂。IT行业中有许多专业术语和缩略语,这些术语通常只为技术人员所熟悉。要想更好地传达技术信息,我们需要使用简单明了的语言来解释这些复杂的术语。


这种方法相比于直接切换到新缓冲区(C-x b bufname RET)有何优势? - bignose
@bignose:我使用ido-mode,通常会打开很多缓冲区。使用C-x b创建一个新的缓冲区会非常繁琐。我必须想出一个唯一的名称,不与当前存在的任何缓冲区匹配。 - paprika

3

我曾经使用过dwj的解决方案,并且对它感到很满意,直到有一天我意识到当你实际上重命名初始缓冲区时(例如通过保存它),它会失败。

然后我采用了这个方案,对我来说效果很好:

  (run-with-idle-timer 1 t
    '(lambda () (get-buffer-create "*scratch*")))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接