I'm aware of
C-x C-e which is
M-x eval-buffer, but these aren't always sufficient to pick up all changes. Sometimes you need to actually close buffers that are in the modes who have had their configuration changed, and other times you need to restart emacs entirely. Is there a more general way of handling this problem? Alternatively, is there a way to restart emacs without losing the existing opened buffers and the interactive history?
I'm aware of
No, it is not possible to reload the modified configuration and have Emacs behave as if those modifications were already in place when Emacs was loaded. In short, Emacs packages have too much freedom for this to be feasible.
You mention that some major modes don't pick up configuration changes. A likely reason for this is that enabling the mode sets some buffer-local variables based on the current values of certain options. Without re-enabling such a mode in every buffer which uses it, not all changes will be picked up. And even then it is quite possible that some things stay unchanged. The odds of this working are higher when the options are customized using a
custom-set-variables form, but this has to be implemented explicitly for each and every option. And so far we have only talked about major modes and their options...
You could attempt to implement a command to re-enable the major mode of each buffer. But it is unlikely that would fully enable all changes, and worse it would disable all minor modes you have manually enabled, and lose all kinds of other state.
For that reason I would even recommend against
eval-buffering your init file at all to pick up as many of the changes as possible. Evaluate the changed settings individually using
eval-last-sexp and if that doesn't work, well then you have to restart Emacs.
How state can be preserved when Emacs is closed is a different question which should be asked separately.
Sometimes you need to actually close buffers that are in the modes who have had their configuration changed
normal-mode is a useful way to re-trigger all the modes for a given buffer, if you've made changes to those or their associated hooks.
You can also use
revert-buffer (which calls
normal-mode), which is sort of like reloading the file without discarding the undo history.
(You can also reload a file with C-xC-v, but that will discard your undo history.)
ibuffer typing upper-case V reverts all marked buffers, while upper-case E and W enable you to evaluate arbitrary elisp for all marked buffers.