ChatGPT解决这个技术问题 Extra ChatGPT

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

如果我不小心关闭了 Emacs 中的暂存缓冲区,我该如何创建一个新的暂存缓冲区?


b
bignose

GNU Emacs 默认绑定:

C-xb *scratch* RET

或者,更详细地说

Mx 切换到缓冲区 *scratch* RET

*scratch* 缓冲区是启动时选择的缓冲区,主要模式为 Lisp Interaction。注意:*scratch* 缓冲区的模式由变量 initial-major-mode 控制。

通常,您可以根据需要创建任意数量的“临时”缓冲区,并根据您的选择命名它们。

C-xb 名称 RET

切换到缓冲区 NAME,如果它不存在则创建它。在您使用 CxCw (或 Mx write-file RET) 选择应保存的文件。

Mx 文本模式 RET

将当前缓冲区的主要模式更改为文本模式。要查找所有可用模式(即,不需要任何新包),您可以通过键入以下内容获取列表:

Mx apropos-command -mode$ RET


注意,scratch 有一些特别之处,至少在 GNU Emacs 21 和更高版本中:切换到一个新的 Scratch 缓冲区会使其回到 Lisp 交互模式。
作为对此的快速跟进,如果您的 .emacs 定义了不同的默认 scratch 模式,则该模式将是新 scratch 的模式 - 而不是列表交互模式.
e
elemakil

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

如果我不想看到暂存缓冲区,请按 Cx Ck ,但它不会杀死它,只需将其放在缓冲区列表的末尾,这样下次我就不需要创建新缓冲区了。


当我从“ibuffer”尝试这个建议时,这个建议被忽略了。但据我所知,“ibuffer”正在使用“kill-buffer”。你能帮助我吗?
好吧,在图形界面中点击“关闭缓冲区”就被删除了。这仅适用于 Cx k,
e
elemakil

this EmacsWiki page 上有很多提示。

这是第一个:

重新创建暂存缓冲区的一个非常简单的函数:

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

S
Steven Huwig

Cx b *scratch* RET y RET 启用 iswitchb 模式。

否则只需 Cx b *scratch* RET。


使用默认绑定,不需要“y RET”,只需将“y”和换行符插入新创建的暂存缓冲区。
哎呀,也许那是来自 iswitchb 模式。对于那个很抱歉。在另一个主题上,试试 iswitchb-mode ;)
一个不应该,也没有什么特别的名字划痕。可以使用 Cx b 创建任意数量的具有任意名称的“临时”缓冲区。
is 名称 *scratch* 有一些特别之处(如已接受的答案中所述) - 如果您创建一个名为 *scratch* 的缓冲区,则主要模式将根据 initial-major-mode 变量设置( lisp-interaction-mode 默认情况下)。
e
elemakil

我在几年前第一次开始使用 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)
;;;----------------------------------------------------------------------

e
elemakil

就像文档字符串说的那样,这个函数将:

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

这将带来一个新的暂存缓冲区,它看起来像初始暂存缓冲区。

(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

我曾经使用 dwj 的解决方案,对此我感到非常高兴,直到有一天我意识到当您实际重命名暂存缓冲区(例如通过保存它)时它失败了。

然后我采用了这个,这对我很有效:

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

e
elemakil

我有 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


这比简单地切换到一个新的缓冲区(Cx b bufname RET)有什么优势?
@bignose:我使用 ido-mode 并且通常打开很多缓冲区。使用 C-x b 创建一个新缓冲区真的很乏味。我必须想出一个与当前存在的任何缓冲区都不匹配的唯一名称。
C
CodyChan
(global-set-key (kbd "C-x M-z")
                '(lambda ()
                   (interactive)
                   (switch-to-buffer "*scratch*")))

这不仅会快速切换到 *scratch* 缓冲区(因为我经常这样做),而且会重新创建一个 *scratch* 缓冲区并在您意外杀死它时自动启用 lisp-interaction-mode。根据需要更改绑定。


n
nj35

请注意,MELPA 中的 emacs 包 unkillable-scratch 会执行此操作。还有 scratch-persist 会在会话之间自动保存和恢复缓冲区。


e
elemakil

这就是我使用的 - 我将它绑定到一个方便的击键。它会将您发送到 *scratch* 缓冲区,无论它是否已经存在,并将其设置为 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

我更喜欢让我的暂存缓冲区成为自动保存的实际文件,重新打开它就像打开文件一样简单。在启动时,我杀死默认设置并找到我自己的这样。

(add-hook 'emacs-startup-hook
  (lambda ()
    (kill-buffer "*scratch*")
    (find-file "/Users/HOME/Desktop/.scratch")))

我有一个自定义的 kill-buffer 函数,它基本上做同样的事情——如果我杀死了最后一个可见缓冲区,则重新打开我的个人暂存文件并终止默认暂存。

我自定义了一些 desktop.el 函数来加载 after (kill-buffer "*scratch*")(find-file "/Users/HOME/Desktop/.scratch"),这样在退出 Emacs 时最后可见的文件不会被默认划痕或我的自定义隐藏启动 Emacs 时从头开始。

我喜欢使用 auto-save-buffers-enhanced,它会自动保存任何未明确排除的文件扩展名:

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

当我想创建一个无文件访问缓冲区时,我使用了@paprika 函数的细微变化:

(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

我已将迄今为止发布的解决方案组合成一个功能:

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

要在 .emacs 中应用此功能,请使用:

(--scratch-buffer t)
(run-with-idle-timer 3 t '--scratch-buffer)

这将使暂存缓冲区一开始就坚不可摧,如果保存,它将被重新创建。此外,我们可以使用快捷功能 scratch 快速调出缓冲区:

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

过去,了解 Emacs 启动的原始启动目录已被证明是有用的。这是 desktop-dirname 的值或暂存缓冲区的 default-directory 局部变量:

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

因此 --startup-directory 将始终返回您的 makefile、TODO 文件等的基本目录。如果没有桌面 (--no-desktop 命令行开关或没有桌面文件)--scratch-directory 变量将保存 Emacs 曾经在其下启动的目录。


Q
Qian

在 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

要添加到已接受的答案,如果您打开了 ILO 模式(并且它在 Cx b 之后自动完成,因此不允许您编写 *scratch*),然后尝试:

C-xb Cb*scratch* RET

C-x b C-b *scratch* RET


I
Ivan Sviatenko

C-xb 然后输入 *scratch* ↩︎

创建一个也处于 lisp 交互模式的新缓冲区。