Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Polymorphic Callbacks in Emacs/Elisp

What's the idiomatic way to implement polymorphic callbacks in elisp?

Specifically, suppose I have a minor mode with a function that performs a certain operation and then invokes another function. This second function should have a different implementation depending on whether the current buffer contains a C++ file or a Java file.

Alternatively, suppose I want to overload variables rather than functions. For example, I want to invoke some external executable, and one of the arguments passed to it differs depending on whether the current buffer has a C++ file or a Java file. I want to be able to construct the command line in a generic function and substitute the one argument depending on the contents of the buffer. Is make-variable-buffer-local the right approach? At what point (and by which mechanism) are these local variables initially supposed to be set?

like image 720
Ray Avatar asked Nov 24 '11 22:11

Ray


2 Answers

I guess you have a variety of approaches. Some options which spring to mind for your callback function are:

  1. Buffer-local variables, as you mentioned.

    How you set it would really depend upon your use case, but you might implement specific major mode hooks, or after-change-major-mode-hook for the general case.

    make-variable-buffer-local is certainly the right approach if you wish the variable to always be buffer-local.

  2. An alist mapping major modes to their associated function.

    Configure this for all the modes you require, and then perform the look-up for the current major mode.

  3. Simply generate the function name based upon the major mode name, calling it if such a function exists.

In all cases, chances are you would use funcall or apply to run the selected function.

Numbers 1 and 2 would also be relevant to the second part of your question.

like image 62
phils Avatar answered Nov 08 '22 10:11

phils


If you're editing a c++ or java file, that buffer should be in c++-mode or java-mode respectively. So you could do something like the following:

(defun function1 ()
  (interactive)
  ;; put your generic code here
  (cond ((string= major-mode "c++-mode")
     (function2-cpp))
    ((string= major-mode "java-mode")
     (function2-java))
    (t (message "I don't know what mode this is"))))

(defun function2-cpp ()
  (message "this is cpp mode"))

(defun function2-java ()
  (message "this is java mode"))
like image 1
Tyler Avatar answered Nov 08 '22 10:11

Tyler