When opening a new file of certain types, I would like some boilerplate to be inserted. That is, when opening a buffer for a file that does not yet exist, insert some predefined text, optionally with some variable interpolation.

Things I can think of as use case:

  • Insert some license text at the start
  • Insert #IF_DEFINED_FOO_H directives in new C header files.
  • Insert some basic targets in a new Makefile

2 Answers 2


See standard library auto-insert.el, which is part of Emacs. To use it, customize options auto-insert and auto-insert-directory, then do this:

(add-hook 'find-file-hook 'auto-insert)

auto-insert is a variable defined in autoinsert.el.

Its value is not-modified


Controls automatic insertion into newly found empty files.

Possible values:

  • nil - do nothing

  • t - insert if possible

  • other - insert if possible, but mark as unmodified.

Insertion is possible when something appropriate is found in auto-insert-alist. When the insertion is marked as unmodified, you can save it with C-x C-w RET.

This variable is used when the function auto-insert is called, e.g. when you do (add-hook 'find-file-hook 'auto-insert). With M-x auto-insert, this is always treated as if it were t.

You can customize this variable.

auto-insert-directory is a variable defined in autoinsert.el.

Its value is "~/insert/"


Directory from which auto-inserted files are taken.

The value must be an absolute directory name; thus, on a GNU or Unix system, it must end in a slash.

You can customize this variable.

See also header2.el.

  • You can also combine auto-insert.el with Yasnippet (for example) to get dynamic or interactive configuration of your boilerplate.
    – nega
    Commented Oct 29, 2018 at 17:33
  • @nega: You might want to post that comment as another answer.
    – Drew
    Commented Oct 29, 2018 at 18:15

At @Drew's suggestion, here's a short example of combining YASnippet and auto-insert to achieve dynamic or interactive boilerplate.

From my ~/.emacs.d/init.el:

;;{{{ yasnippet & auto-insert

(use-package yasnippet
  (add-to-list 'yas-snippet-dirs "~/.emacs.d/snippets")
  (yas-global-mode 1))

(defun nega/yas-cmake-bp ()
  (yas-expand-snippet (yas-lookup-snippet "cmake_minimum_required" 'cmake-mode)))

(use-package autoinsert
  (setq auto-insert-query nil)
  (auto-insert-mode 1)
  (add-hook 'find-file-hook 'auto-insert)
  (setq auto-insert-alist nil) ;; remove this like to restore defaults
  (add-to-list 'auto-insert-alist  '("CMakeLists\\.txt$" . [nega/yas-cmake-bp])))


Block-by-block, we:

  • Load yasnippet, set the user-defined snippet location to ~/.emacs.d/snippets, and enable yasnippet globally
  • Define a callable function that "executes" the snippet named "cmake_minimum_required" from the "cmake-mode" snippet table
  • Load autoinsert and configure it to
    • Do not ask when inserting
    • Enable auto-insert-mode globally
    • Run auto-insert when a new file is opened
    • Delete any default "auto inserts"
    • Add a filespec + function pair to the list of "auto inserts"

With these three blocks of elisp, every time I open a new file named "CMakeLists.txt", the following YASnippet snippet will be "executed" and the corresponding text will be inserted in to the new buffer.

# name: cmake_minimum_required
# key: cmr
# --
cmake_minimum_required(VERSION ${1:`cmake-mode-cmake-version`}${2: FATAL_ERROR})

The buffer for my new "CMakeLists.txt" looks like:

cmake_minimum_required(VERSION 3.11.1 FATAL_ERROR)

The cursor is at the location of the carrot, ie: before the "3". My snippet has found the current version of CMake on my system, and inserted it at that point. This is an editable field, so I change it if I wish. If I edit it, or not, I hit TAB to move to the next field, which is " FATAL_ERROR". (Yes, in this case it contains the space.)

FATAL_ERROR is an optional argument to cmake_minimum_required(). If I want to keep it, I can press TAB again or Ctrl+d to delete it. Either way the cursor moves to first column of the second line, and we're ready to continue typing.

Note that you can have "traditional auto inserts" and "YASnippet auto inserts" in auto-insert-alist. But, you will run into trouble if your filespecs overlap.

  • FWIW it'd be more "correct" to use :hook (find-file . auto-insert) than doing add-hook in custom.
    – Duncan W
    Commented Jan 23, 2022 at 4:14

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.