find-file-noselect you have no control about what actually happens, and you may end up with arbitrary minor modes enabling in the buffer, depending on what the user enabled in their
init.el. Also, cleanup is hard.
insert-file-contents instead. If you need specific major or minor modes in the buffer, enable them explicitly. To write files, use
with-temp-file instead, which—despite its name—lets you write to arbitrary files.
find-file-noselect has a lot of side-effects, including
- interactively asking questions (that alone is a no-go in non-interactive use),
- automatically enabling view mode for readonly files,
- entering normal mode otherwise,
- and running
Normal Mode itself
- automatically selects a proper major mode for the current buffer,
- runs all corresponding major and minor mode hooks,
- and reads all local variables for the current buffer, i.e. file variables and directory variables, which again may ask interactive questions about unsafe local variables.
Since all hooks are run, you get all minor modes and hook functions the user enabled in their
init.el, which can cause everything, from minor inconveniences (if undesirable minor modes are enabled) to major havoc (if the user added a hook function that expects to be called from an interactive context).
See https://github.com/flycheck/flycheck/issues/366 for an example. The use of
find-file-noselect caused a data file to be syntax-checked by Flycheck, and since it was happening at Emacs shut-down, there was no time to properly clean up again, leaving a temporary file behind.
find-file-noselect you need to be extra careful to kill the buffer again.
find-file-noselect does not do that for you.
You need to remember the buffer at some place, and carefully use
unwind-protect to make sure that the buffer gets killed even in case of non-local exits.
To read files, use
insert-file-contents, which only does the most basic things, e.g. coding system conversion, but does not ask questions, enable hooks, or setup local variables:
(insert-file-contents (locate-user-emacs-file "foo.el"))
;; Enter the major mode explicitly
with-temp-buffer takes care to properly kill the temporary buffer at the end of its body.
To write files, use
with-temp-file, which creates a temporary buffer and writes the contents to the given file name at the end of its body:
(with-temp-file (locate-user-emacs-file "foo.el")
(prin1 (list 'my 'data) (current-buffer)))