3

I am using GNU Emacs 26.3 (build 1, x86_64-w64-mingw32) of 2019-08-29. In my .emacs I specifically asked not to show the startup screen or buffer *scratch*:

(custom-set-variables
 '(inhibit-startup-screen t)
 '(initial-buffer-choice nil))

However, whenever I open a file with emacs (or runemacs), the window is split in half, showing both the *scratch* buffer and the file I opened. How do I get rid of showing the *scratch* buffer when I start Emacs?

2
  • How are you opening a file?
    – Drew
    Commented Jul 17, 2020 at 22:22
  • Every possible ways I can think of: 1) emacs filename 2) runemacs filename 3) right click on the file and sendto "runemacs" and "emacs" etc... all behave the same.
    – tony
    Commented Jul 19, 2020 at 2:10

2 Answers 2

3

I battled with this phenomenon for years and discovered that Emacs automatically recreates a scratch buffer if there are no other buffers. In addition, Emacs creates a scratch buffer on startup. There are a variety of factors that affect how buffers are displayed on startup, including, but not limited to the hard coded (baked-in) startup.el. The startup.el file cannot be changed without rebuilding Emacs subsequent thereto so that those changes can be incorporated into the build itself. People who use the popular desktop.el library to restore a previous layout are necessarily using the after-init-hook to restore the prior session -- so that can affect what buffer is displayed when Emacs starts. I would suggest using the emacs-startup-hook, which runs later than the after-init-hook, to either bury the scratch buffer or kill it. Another idea that I just thought of, but haven't tested, is to set the initial-major-mode variable to the value of a custom function that deals with how you wish to handle that buffer -- but the O.P. may need to experiment with when that setting gets taken into consideration during startup. There are other factors to consider such as newer versions of Emacs add support for an early-init.el file where settings can be stored. Here is an example utilizing the emacs-startup-hook:

(add-hook 'emacs-startup-hook (lambda ()
                                (when (get-buffer-window "*scratch*")
                                  (bury-buffer "*scratch*"))))

Feel free to play around with that example and customize it to suit your needs; e.g., (kill-buffer "*scratch*") instead of burying it, then put your preferred buffer in its place with set-window-buffer to set the desired buffer in the desired window ... the sky is the limit.

Here is another example using the emacs-startup-hook that kills the *scratch* buffer if it exists even if it is not presently displayed in a window:

(add-hook 'emacs-startup-hook (lambda ()
                                (when (get-buffer "*scratch*")
                                  (kill-buffer "*scratch*"))))
5
  • Thanks. But that doesn't make sense that emacs insists on creating a new buffer because it's opening an existing file. I tried your suggestions, that bury-buffer didn't work, but the kill-buffer worked. However, now I have that opened file in a split window because the the scratch buffer was killed and it's replaced with the opened file. Another strange thing is that I have another pc running windows 10, and the same .emacs setting and the other one doesn't have this problem.
    – tony
    Commented Jul 19, 2020 at 2:23
  • In terms of understanding when Emacs creates a *scratch* buffer, there are two places you can look to study the code: (1) M-x find-library RET startup RET and then word-search that Lisp library for all of the occurrences of (get-buffer-create "*scratch*") -- see which, if any, apply to your use-case. (2) Have a look at the source code used to build Emacs at the function init_buffer_once at the line that states: Fset_buffer (Fget_buffer_create (build_pure_c_string ("*scratch*"))) -- init_buffer_once is called by the function main in emacs.c. Feel free to study the code more.
    – lawlist
    Commented Jul 19, 2020 at 6:10
  • I would suggest one of two approaches to your use-case: (1) use delete-window to delete whichever window you don't want being sure to test first for whether more than one window exists and the buffers that are being displayed in the windows; (2) use delete-other-windows ensuring that you have focus in the window that you want to keep. delete-window has an optional argument for a specific window. You might try placing some messages in the example function in the answer and see how many windows are visible when the emacs-startup-hook runs, and what is displayed in the window(s).
    – lawlist
    Commented Jul 19, 2020 at 6:14
  • 1
    As an addendum to the second comment underneath this answer, I see a few other calls to creating the *scratch* buffer in the C source code using Fget_buffer_create (scratch) ... the function init_buffer, the function other_buffer (aka other-buffer), and the function other_buffer_safely. There may be other references in the C source code where the *scratch* buffer gets created ... I've only done some minimal grepping of the Emacs 26.3 source code to post the comments herein and hereinabove.
    – lawlist
    Commented Jul 19, 2020 at 6:29
  • Yes, instead of using bury-buffer or kill-buffer, use delete-window-on worked! Thanks! (add-hook 'emacs-startup-hook (lambda () (when (get-buffer "scratch") (delete-windows-on "scratch"))))
    – tony
    Commented Jul 20, 2020 at 15:40
0

Using window-buffer-change-functions I finally got rid of *scratch*.

UPDATED 2024-05-24

(defun buffer-change-hook (frame)
  (unless
      (seq-every-p
       (lambda (elt) (string-match "^ *\\*" (buffer-name elt)))
       (buffer-list))
    (kill-buffer "*scratch*")))

ORIGINAL

The original version only works well if emacs opens some file initially. If we just run emacs and then open another file (C-x C-f file-name), it fails to open it.

(defun buffer-change-hook (frame)
  (unless (string-equal (buffer-name (current-buffer)) "*scratch*")
      (kill-buffer "*scratch*")
    )
  )

(add-hook 'window-buffer-change-functions 'buffer-change-hook)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.