2005-08-14

How Does Emacs Know Which Functions Are Interactive

When you do M-x foo in emacs, you are asking emacs to execute an interactive function named "foo". The function must be declared in a special way as follow:
 
(defun foo/1 ()
  (interactive)
  (if (eq some-condition t)
      (execute "rm -rf /")))

The form on the second line, "(interactive)", tells emacs that this function is an interactive function.

But how does the emacs knows you put that form in that function? It could try to execute the function, but it may produce an unwanted side-effect (like executing "rm -rf /" if the condition is met).

Could you do a partial execution, e.g.: when a function is defined, execute only the first form and don't execute the rest? But that does not explain the following capability:
 
(defun foo/2 (do-the-rm-rf)
  (interactive (list (read-string "Run rm -rf /?" "N")))
  (if (string= do-the-rm-rf "Y")
      (execute "rm -rf /")))

(defun call-foo/2 ()
  (funcall 'foo/2 "N"))

(defun call-foo/3 ()
  (interactive (list (execute "rm -rf /"))))

When you do M-x foo/2, emacs would first run the read-string function, prompt the user, get the answer from user, and then run the function foo/2. But if you call foo/2 non-interactively by calling it from another function like in call-foo/2, emacs will not prompt the user at all.

Well, that blows the hypotheses that when a function is defined, emacs executes only the first form. There could be no execution whatsoever since doing so may cause severe side-effect. What if the execute form in call-foo/3 is executed? Bad, bad, bad.

So, where is the magic?

The magic lies in macro

defun is actually a special form call. A special form is a form that may be implemented and/or executed differently. If a form is implemented in non-elisp language, it is a special form. If a form is not a function call form, it is a special form (ordinarily, '(something)' in elisp would execute the function 'something').

A special form basically can do anything to its body (macro), including scanning for the interactive form when it is called, just like what the special form defun does.

(originally from http://microjet.ath.cx/WebWiki/HowDoesEmacsKnowWhichFunctionsAreInteractive.html)

No comments: