3

How can I easily reload file-local variables, after I have changes their values in the file buffer?

I know a work around

Save and close the file and re-open.

But this is pretty cumbersome.

  • 1
    M-: (hack-local-variables) – gigiair Jun 24 at 7:01
2

I stumbled myself over a way to do this when looking at the Elisp code in files.el:

M-x normal-mode

This command re-applies the local file variable list by calling the function hack-local-variables. However normal-mode does a lot of other stuff too, so this is not just re-reading the local variables...

  • This is what the documentation suggests: " Use the command ‘M-x normal-mode’ to reset the local variables and major mode of a buffer according to the file name and contents, including the local variables list if any" – JeanPierre Jun 24 at 7:16
1

I just use find-alternate-file which is bound to C-x C-v by default. C-x C-v Ret is lightning fast for me. revert-buffer will also work, but M-x revert-buffer Ret is more typing.

Both of these options will reset local variables. For instance, if you have indent-tabs-mode: nil in your local variable list and you remove it outright, save, find-alternate-file or revert-buffer your buffer, indent-tabs-mode will now be set to t (assuming you haven't changed its default elsewhere of course.) Note: I only confirmed this with file-local variables, and not directory-local variables.

@drew brings up a good point. If you're not careful, or use these functions non-interactively you can overwrite unsaved changes in your buffer. Also, if you have unsaved changes, using these functions can break your flow. find-alternate-file will ask to save your buffer, and revert-buffer will ask to overwrite your unsaved changes. As you develop muscle memory and good editing habit, you'll find it gets in your way less and less.

  • That's generally what I do too (I have <f5> bound to reverting without confirmation). But of course reverting can lose other changes too, so you might want to save the buffer or some other things before doing it. – Drew Jun 24 at 14:18
0

I use quite often hack-local-variables to set the file local variables without side-effect (such as re-loading the major mode). giglair already suggested that in his comment.

Warning: It does not reset local variables. That means if you remove a variable from the list of local variables this variable is still bound (and set to the old value) after running hack-local-variables. I think that could be the reason why it is just a function and not an interactive command.

You can easily turn hack-local-variables into an interactive command with the following advice:

(defun hack-local-variables-make-interactive (&rest _args)
  "Just add the `interactive'-specification to `hack-local-variables'."
  (interactive))

(advice-add 'hack-local-variables :before #'hack-local-variables-make-interactive)

I most often need hack-local-variables in Orgmode files. Therefore I wrote a context-aware binding for C-c C-c. It runs hack-local-variables when it is in a Local Variables section of an Orgmode document.

(require 'subr-x)
(require 'org)

(defun org+-ctrl-c-ctrl-c-local-variables (&optional noerror)
  "Run `hack-local-variable' when we are in the \"Local Variables\" section.
If the Local Variables section is not found and NOERROR is nil or omitted
this function signals a user error."
  (interactive "P")
  (save-excursion
    (when-let ((heading (condition-case nil
                (save-excursion
                  (org-back-to-heading t)
                  (when (looking-at "\\*[[:space:]]")
                (cons (point)
                      (org-get-tags))))
              (error nil)))
           (heading-pos (car heading))
           (heading-tags (cdr heading))
           (re "^[[:space:]]*\\(#+\\)?[[:space:]]*\\(local[[:space:]]+\\(variables\\)\\|\\(end\\)\\):[[:space:]]*$")
           (local-variables-start
        (progn
          (save-excursion (re-search-backward re heading-pos t))
          (match-string 3)))
           (in-comment (match-string 1))
           (local-variables-end
        (progn
          (re-search-forward (format "%s\\|^\\*+[[:space:]]" re) nil t)
          (match-string 4))))
      (if (and local-variables-start local-variables-end
           (or in-comment
           (member "noexport" heading-tags)))
      (progn
        (hack-local-variables)
        (message "Hacked local variables")
        t)
    (user-error "Local Variables not found")
    ))))

(add-to-list 'org-ctrl-c-ctrl-c-hook #'org+-ctrl-c-ctrl-c-local-variables)

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.