【发布时间】:2010-09-19 02:18:39
【问题描述】:
如果我不小心关闭了 Emacs 中的 scratch 缓冲区,如何创建一个新的 scratch 缓冲区?
【问题讨论】:
标签: emacs
如果我不小心关闭了 Emacs 中的 scratch 缓冲区,如何创建一个新的 scratch 缓冲区?
【问题讨论】:
标签: emacs
GNU Emacs 默认绑定:
C-xb
*scratch*RET
或者,更详细的
M-x
switch-to-buffer *scratch*RET
*scratch* 缓冲区是启动时选择的缓冲区,主模式为Lisp Interaction。注意:*scratch* 缓冲区的模式由变量initial-major-mode 控制。
通常,您可以根据需要创建任意数量的“临时”缓冲区,并根据您的选择命名它们。
C-xb
NAMERET
切换到缓冲区NAME,如果它不存在则创建它。在您使用 CxCw (或 Mx write-file RET) 选择应保存的文件。
M-x
text-modeRET
将当前缓冲区的主要模式更改为文本模式。要查找所有可用模式(即不需要任何新包),您可以通过键入以下内容获取列表:
M-x
apropos-command -mode$RET
【讨论】:
.emacs 定义了不同的默认 scratch 模式,这将是新 scratch - 不是列表交互模式。
我在我的 .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 缓冲区,我按 Cx Ck ,但它不会杀死它,只是放在缓冲区列表的末尾,所以下次我需要它不必创建新的。
【讨论】:
this EmacsWiki page 上有一大堆提示。
这是第一个:
一个非常简单的重新创建暂存缓冲区的函数:
(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 启用 iswitchb 模式。
否则只需 C-x b *scratch* RET。
【讨论】:
initial-major-mode 变量(默认为lisp-interaction-mode)。
我是几年前第一次开始使用 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)
;;;----------------------------------------------------------------------
【讨论】:
正如文档字符串所说,这个函数将:
切换到暂存缓冲区。如果缓冲区不存在,则创建它并将初始消息写入其中。"
这将带来一个新的暂存缓冲区,看起来像初始暂存缓冲区。
(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)
【讨论】:
我曾经使用 dwj 的解决方案,我对此非常满意,直到有一天我意识到它失败了,当你真正重命名暂存缓冲区(例如通过保存它)时。 p>
然后我采用了这个,这对我很有效:
(run-with-idle-timer 1 t
'(lambda () (get-buffer-create "*scratch*")))
【讨论】:
我有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
【讨论】:
bufname RET) 有什么优势?
ido-mode,通常会打开很多缓冲区。使用C-x b 创建一个新缓冲区真的很乏味。我必须想出一个与任何当前存在的缓冲区都不匹配的唯一名称。
(global-set-key (kbd "C-x M-z")
'(lambda ()
(interactive)
(switch-to-buffer "*scratch*")))
这不仅会快速切换到*scratch* 缓冲区(因为我经常这样做),而且会重新创建一个*scratch* 缓冲区并在您意外杀死它时自动启用lisp-interaction-mode。随意更改绑定。
【讨论】:
请注意,MELPA 中的 emacs 包 unkillable-scratch 会执行此操作。还有scratch-persist会在会话之间自动保存和恢复缓冲区。
【讨论】:
这就是我使用的 - 我将它绑定到一个方便的按键。它会将您发送到*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)))
【讨论】:
我更喜欢让我的暂存缓冲区成为自动保存的实际文件,重新打开它就像打开文件一样简单。在启动时,我会杀死默认设置并像这样找到自己的。
(add-hook 'emacs-startup-hook
(lambda ()
(kill-buffer "*scratch*")
(find-file "/Users/HOME/Desktop/.scratch")))
我有一个自定义的 kill-buffer 函数,它基本上做同样的事情 - 重新打开我的个人暂存文件并终止默认暂存 如果我杀死了最后一个可见缓冲区。
我自定义了一些 desktop.el 函数来加载之后 (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) ))
【讨论】:
我已将迄今为止发布的解决方案合并为一个功能:
(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 曾经在其下启动的目录。
【讨论】:
在 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))
【讨论】:
要添加到已接受的答案,如果您打开了 ILO 模式(并且它在 Cx b 之后自动完成,因此不允许您编写 *scratch*),那么试试:
C-xb C-b
*scratch*RET
C-x b C-b *scratch* RET
【讨论】:
C-xb 然后输入
*scratch*↩︎
创建一个也处于 lisp 交互模式的新缓冲区。
【讨论】: