I would like emacs to check for a ~/emacs.d/scratch.txt and use it's contents instead of the default message when emacs starts.

How can this be done?


This will do the job.

(let ((filename "~/.emacs.d/startup.txt"))
  (when (and (file-exists-p filename)
             (get-buffer "*scratch*"))
    (with-current-buffer "*scratch*"
      (insert-file-contents filename))))
  • Perfect! No initial-buffer-choice needed. – ideasman42 Feb 10 '18 at 12:19
  • Update, one down side is you can see the buffers changing at startup, updating own answer with different solution. – ideasman42 Feb 13 '18 at 2:29
  • I've edited own answer based on this one - which only runs when no other buffers are loaded (avoiding flickering at startup) – ideasman42 Feb 17 '18 at 21:51

initial-buffer-choice allows to specify a path to a file or directory:

(let ((filename "~/.emacs.d/startup.txt"))
  (when (file-exists-p filename)
    (setq initial-buffer-choice filename)))
  • 1
    This has a fairly big disadvantage that the file gets loaded, so running emacs somefile.txt will not show the file given in the command line, but the startup file instead. It also doesn't use the scratch buffer name which is ignored for buffer switching in some cases. – ideasman42 Feb 10 '18 at 8:15
  • Well, you're changing what the initial buffer is, so it's hardly surprising it's not named *scratch* anymore. As for the other thing, if I run emacs somefile.txt, it opens that file in a split, additionally to the buffer I've specified. This is hardcoded in startup.el. – wasamasa Feb 10 '18 at 9:39
  • 1
    My aim was simply to have text from a file to replace the default text in *scratch*, not to open a file or split windows. Basically, if I open emacs with no files: show a buffer with useful content, otherwise behave as normal. – ideasman42 Feb 10 '18 at 9:59

This can be done using initial-buffer-choice,

While initial-buffer-choice can be set to a filename, this will load the file as well as any files passed via the command line (splitting the window or not even showing the buffer depending on your setup).
So reading file data into *scratch* buffer has the advantage that exact behavior is preserved, just replacing the text.

;; no startup screen
(setq inhibit-startup-screen t)

;; use startup.txt instead
(setq initial-buffer-choice
  (lambda ()
    (let ((oldbuf (current-buffer)))
      ;; optional, I prefer only do this when no files are loaded.
      (if (buffer-file-name)
        oldbuf ;; only run when no files are loaded.
        (let ((filename "~/.emacs.d/startup.txt"))
          (with-current-buffer (get-buffer-create "*scratch*")
            (if (file-exists-p filename)
              (insert-file-contents filename)
              (insert (format ";; Scratch buffer, create '%s' to replace this text on startup." filename)))
            (set-buffer oldbuf)))))))

Others might suggest how this can be done better, it seems to work well enough though.

  • 1
    With proper indentation and the closing parentheses not spread apart. – wasamasa Feb 9 '18 at 9:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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