I'm currently trying to move from vim to emacs so be gentle with me ;)

In Vim, one of my favorite features is auto commands, I'll have one for each project for example:

au BufEnter c:/projects/foo/* :call FooSetup()
au BufEnter c:/projects/bar/* :call BarSetup()

This will call the correct setup whenever I switch buffers and change setting like the root directory, make program, error format etc.

The closest emacs equivalent I've been able to find is mode hooks, which seem much more limited.

Edit - The solution, by combining both answers below:

(defun my/test ()
  (when (and buffer-file-name (string-match "c:/projects/foo/.*" (buffer-file-name)))
    (message "foo")
    (setq default-directory "c:/projects/foo"))
  (when (and buffer-file-name (string-match "c:/projects/bar/.*" (buffer-file-name)))
    (message "bar")
    (setq default-directory "c:/projects/bar")))
(add-hook 'buffer-list-update-hook #'my/test)
  • 1
    Have a look at .dir-locals.el or Directory Variables. Jan 14, 2016 at 2:50
  • Thanks, I think that's exactly what I'm after. Will this work when switching between buffers/windows as well?
    – flukus
    Jan 14, 2016 at 3:12
  • Actually, it looks like this doesn't cut it. Only variables can be set, you can't do things like changing directories.
    – flukus
    Jan 16, 2016 at 21:31
  • 1
    It is possible but probably not exactly as you might be doing in vim. If you give a specific use case, I can give an answer for that. Usually you either set the correct hooks, enable correct minor modes or use dir or file local variables. Jan 16, 2016 at 21:34
  • 1
    I don't use it myself, but you mind find projectile useful. Among other things, it provides quick navigation among files in a project.
    – Tyler
    Jan 19, 2016 at 14:12

2 Answers 2


You need the buffer-list-update-hook.

From C-h v buffer-list-update-hook,

Hook run when the buffer list changes.
Functions running this hook are, get-buffer-create, make-indirect-buffer, rename-buffer, kill-buffer, bury-buffer-internal and select-window.

You can check out the More Standard Hooks section in the Emacs Lisp Reference Manual for info about this and other standard hooks too.

As an example, check out the below snippet which, after evaluating, will show you the current buffer name after switching buffers.

(defun my/test ()
  (message (buffer-name)))
(add-hook 'buffer-list-update-hook #'my/test)

If you have the projectile package installed, you can use the projectile-project-root function, to get the current buffer project root directory.

  • Careful though, this hook is run very often, including every time a temporary buffer is used (because it needs to be created and killed).
    – wasamasa
    Jan 19, 2016 at 6:23
  • @wasamasa +1. Another approach would be to have something like (let ((default-directory (projectile-project-root)))..) in whichever function that is using the default-directory variable. Jan 19, 2016 at 12:03

The most similar way to do it in emacs would probably be to use find-file-hook:

(defun some-directory-setup ()
  (when (string-match "/path/to/dir/.*" (buffer-file-name))
    (..do stuff..)))
(add-hook 'find-file-hook 'some-directory-setup)

As for using .dir-locals.el, you can use eval if you want to do something other than change settings. For example, you could have ((nil . ((eval . (message "Hello world."))))) in the .dir-locals.el file to execute actual code.

  • I'll play around with this, but from what I've read this even only fires when a file is first loaded and not when you switch between windows, is that correct?
    – flukus
    Jan 18, 2016 at 3:03
  • buffer-list-update-hook is somewhat similar (it will run whenever you switch buffers). I don't understand what you would be doing that would need this though. EDIT: I see someone else answered; glad you found what you need.
    – noctuid
    Jan 18, 2016 at 16:50
  • For buffer local variables your solution would work fine. For global ones though you need it to run on every window change. See my edit in the question.
    – flukus
    Jan 18, 2016 at 20:38
  • @flukus What global variable is there that you don't want to make buffer local? default-directory is normally buffer local isn't it?
    – noctuid
    Jan 20, 2016 at 20:13
  • It looks that way, this is one of the things I'm still learning :)
    – flukus
    Jan 20, 2016 at 20:55

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.