Search code examples
emacsdefadvice

Override interactive function with advice


How can I override interactive input with defadvice in elisp?

For example, I am trying to stop ansi-term from prompting for input with the following:

(defadvice ansi-term (around kill-interactive activate)
  (let ((explicit-shell-file-name "/bin/bash"))
    (ad-set-arg 0 explicit-shell-file-name)
    (deactivate-input-method)
    ad-do-it))

But, it still prompts even though explicit-shell-file-name is set correctly.


Solution

  • The function still has its original interactive declaration, so if you call it interactively, it will use it to obtain argument values.

    You can replace the interactive form by including it in your advice. e.g.:

    (defadvice ansi-term (around kill-interactive activate)
      (interactive (list "/bin/bash" nil))
      ad-do-it)
    

    And indeed that's exactly where you should be setting the argument value if using advice like this, otherwise you're clobbering the PROGRAM value for non-interactive uses of ansi-term as well, which is clearly not what you want here!

    Personally I wouldn't do any of that, however. I'd define a new wrapper command, and invoke that instead:

    (defun bash ()
      "Run bash inside `ansi-term'."
      (interactive)
      (ansi-term "/bin/bash"))
    

    If you have any keybindings for ansi-term you could then remap them like so:

    (global-set-key [remap ansi-term] 'bash)