Local variables

See also: FileLocalVariables, DirectoryVariables

There are two things you can do to force variable changes local to files, when you load them.

The easiest thing is to add values to the first line, like this (all examples taken from the Emacs info page, “File Variables” (but the page’s first line reads “Local Variables in Files”)):

 -*- mode: MODENAME; VAR: VALUE; ... -*-

Here is an example:

 ;; -*- mode: Lisp; fill-column: 75; comment-column: 50; -*-

As you can see, you can start with whatever comment syntax is necessary. You can add other mode commands to this line as well (for minor modes); in my text files for example I often use mode: text; mode: auto-fill; mode: filladapt. (But if sharing a document be careful about putting personal preferences; fill-column is a property of the document, but auto-fill is only really for user interaction.)

The other way to do this is to add a “Local Variables” section to the end of the document, like this:

     ;;; Local Variables: ***
     ;;; mode:lisp ***
     ;;; comment-column:0 ***
     ;;; comment-start: ";;; "  ***
     ;;; comment-end:"***" ***
     ;;; End: ***

The prefix (”;;;”) and suffix (”***”) can be whatever is needed to turn these lines into comments in the file. If one or the other is not needed, they can be omitted; but if used, they must be the same on each line so that Emacs knows which parts of each line to read.

You can evaluate lisp code here, too:

 Local Variables:
 eval: (crs-auto-encrypt)

…but Emacs will ask you whether you want to arbitrarily run this code when you open the document, to save you from Trojan horses and the like. You can change this by changing enable-local-eval to t. Don’t do this.

mode hooks and local variables

Mode hooks execute before local variables are processed, so your hooks cannot respond to local vars at that point in time (specifically, ‘normal-mode’ calls ‘set-auto-mode’ and ‘hack-local-variables’ in that order).

We can use ‘hack-local-variables-hook’ to resolve this problem.

Method A

 ;; Use the regular major mode hook to add a buffer-local hack-local-variables-hook
 (add-hook 'python-mode-hook 'my-python-mode-hook)
 (defun my-python-mode-hook ()
   (add-hook 'hack-local-variables-hook
             (lambda () (message "local variables visible here"))))
             nil t))

Method B

 ;; Provide a new MAJORMODE-local-vars-hook
 (add-hook 'hack-local-variables-hook 'run-local-vars-mode-hook)
 (defun run-local-vars-mode-hook ()
   "Run a hook for the major-mode after the local variables have been processed."
   (run-hooks (intern (concat (symbol-name major-mode) "-local-vars-hook"))))
 ;; Use our new hook as required
 (add-hook 'python-mode-local-vars-hook
           (lambda () (message "local variables visible here")))