4

I want to make it so that I have interactive functions that can only be called from buffers in a certain directory, like variables in .dir-locals.el. Is there a way to do this?

For example, say I'm writing a program that has configuration files. I'd like to be able to invoke M-x new-conf, which will make a new conf file in the same directory as the buffer I invoke it in. However, I only want to be able to call it from buffers in a certain directory.

  • 3
    No, there is no mechanism for buffer-local values for a symbol's function slot. Please give an example of what you would like to achieve. There are likely numerous ways in which you could attain the desired effect without the specific feature you've asked about. (n.b. If you only care about invoking the commands by key bindings, that is highly relevant information.) – phils Oct 18 '15 at 3:26
  • @Trebuchette You can have a minor mode define those functions and have that minor mode enabled using .dir-locals.el. – Kaushal Modi Oct 18 '15 at 5:14
  • 2
    kaushalmodi: That defers the definition of the commands to the first time that the minor mode is enabled, but the command is thenceforth available to all buffers (as is every loaded -- or autoloaded -- command). – phils Oct 18 '15 at 11:51
5

So as per my earlier comment, Emacs doesn't really support what you're asking for.

I would strongly recommend that you simply define a global command in the normal way, and make it behave appropriately based on the presence or not of a local variable (which could be directory-local). It can still be called from anywhere, but you would ensure that it never did something 'bad'.

Or come up with a key binding for your command -- it's easy [1] [2] to have key bindings which are only available in certain buffers.

If you're really dead-set on the command not being available via M-x then the following is the cleanest and most robust approach I can think of (but it's still an ugly hack).

(defun my--real-command ()
  "The real command; we'll leave this permanently defined."
  (interactive)
  (message "Hello, world."))

(defun my-pre-command-hook ()
  "Define or undefine `my-command' based on `my-dir-local-flag'."
  (when (eq this-command 'execute-extended-command)
    (if (bound-and-true-p my-dir-local-flag)
        (defalias 'my-command 'my--real-command)
      (fmakunbound 'my-command))))

(add-hook 'pre-command-hook 'my-pre-command-hook)
  • kaushalmodi: Thanks for fixing the typo. I'll leave the links ([1][2]) you added, although that wasn't actually what I had in mind -- It's rather simpler to define a minor mode for the keymap you want, and use the local variable block to simply enable that mode. – phils Oct 20 '15 at 14:16

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.