[comp.emacs] redefining functions in gnuemacs

weissman@apollo.uucp (Mark Weissman) (05/09/88)

Here's a macro that takes an existing function and adds
before and after hooks to it.   It may lose for some
interactive arguments but its great for things like
checking parenthesis before saving a file etc.

Its used like:
(mdw:add-hooks some-existing-function)
(setq 
  mdw:some-existing-function-before-hooks '(func-1 func-2 ...)
  mdw:some-existing-function-after-hooks  '(func-3 func-4 ...))

Mark Weissman
APOLLO Computer Inc.

;;; -*- Mode: Emacs-Lisp -*-
(defvar mdw:gensym-name "GENSYM")
(defvar mdw:genysm-number 0)
(defmacro mdw:gensym ()
  "Generate a new unused symbol"
  (let (s)
    (while (or (boundp (setq s (intern (format "mdw:%s-%s"
                                               mdw:gensym-name
                                               (setq mdw:gensym-number
                                                     (1+ mdw:gensym-number))))))
               (fboundp s)))
    (list 'quote s)))

(defmacro mdw:add-hooks (function)
  "This macro is called with a symbol representing an emacs lisp
          function.  This function is redefined to funcall a list
          of hooks before and after function execution.
	  This will may lose with complex (interactive) args.
          This will create local-variables as follows:
          mdw:<function-name> bound to the symbol function of function
          mdw:<function-name>-documentation which will be the doc
                string for the function.
          mdw:<function-name>-before-hooks, a list of functions to funcall
                before execution. These functions will be called with the
                same arguments as the original function.
          mdw:<function-name>-after-hooks, a list of functions to funcall
                after execution.  These functions will be called with the
                result of executing the original function followed by the
                original arguments.
          This will take and return the same arguments as the original function.
          "
  (let* ((mdw-name   (concat "mdw:" (symbol-name function)))
         (mdw-before (concat mdw-name "-before-hooks"))
         (mdw-after  (concat mdw-name "-after-hooks"))
         (mdw-doc    (concat mdw-name "-documentation"))
         (args       (mdw:gensym))
         (hook       (mdw:gensym))
         (result     (mdw:gensym)))
    (if (fboundp function)
        (list 'progn
              (list 'defvar (intern mdw-name)
                    (list 'symbol-function (list 'quote function)))
              (list 'defvar (intern mdw-doc)
                    (list 'documentation   (list 'quote function)))
              (list 'defvar (intern mdw-before) nil)
              (list 'defvar (intern mdw-after)  nil)
              (list 'defun function (list '&rest args)
                    (concat
                      (if (boundp (intern mdw-doc))
                          (eval (intern mdw-doc))
                          (documentation function))
                      "\n\nAdded hooks: " mdw-before " &\n"
                      "             " mdw-after ".")
                    '(interactive)
                    (list 'mapcar
                          (list 'function
                                (list 'lambda (list hook)
                                      (list 'apply hook args)))
                          (intern mdw-before))
                    (list 'let
                          (list
                            (list result (list 'apply (intern mdw-name) args)))
                          (list 'mapcar
                                (list 'function (list 'lambda (list hook)
                                                      (list 'apply hook args)))
                                (intern mdw-after))
                          result))))))

liberte@uiucdcsm.cs.uiuc.edu (05/11/88)

/* Written 10:06 am  May  5, 1988 by jwg1@bunny.UUCP in uiucdcsm:comp.emacs */
/* ---------- "redefining functions in gnuemacs" ---------- */
I would like to invoke a function every time delete-file is called.
There doesn't appear to be a delete-file-hooks.  Can I redefine
delete-file and still use the old delete-file somehow ? 
-- 
Jim Gish
/* End of text from uiucdcsm:comp.emacs */

You can redefine delete-file as you suggest.  To get the current
function for a symbol, use the symbol-function function, e.g.
(setq old-delete-file (symbol-function 'delete-file))

However, delete-file is a primitive function and any calls to a
primitive by a primitive will not use a lisp redefinition.  There
is a call of delete-file in the rename-file primitive.

dan

jr@PEBBLES.BBN.COM (John Robinson) (05/12/88)

>> Someone has also posted some code for adding hooks to arbitrary
>> functions; this is probably the best way to go, but I don't
>> recall the poster.

Here 'tis...

/jr
jr@bbn.com or bbn!jr
--------
Date: 8 May 88 17:22:00 GMT
From: Mark Weissman <apollo!weissman@EDDIE.MIT.EDU>
Organization: Apollo Computer, Chelmsford, Mass.
Subject: redefining functions in gnuemacs
Message-Id: <3bee854e.12972@apollo.uucp>
Sender: unix-emacs-request@BBN.COM
To: unix-emacs@BBN.COM

Here's a macro that takes an existing function and adds
before and after hooks to it.   It may lose for some
interactive arguments but its great for things like
checking parenthesis before saving a file etc.

Its used like:
(mdw:add-hooks some-existing-function)
(setq 
  mdw:some-existing-function-before-hooks '(func-1 func-2 ...)
  mdw:some-existing-function-after-hooks  '(func-3 func-4 ...))

Mark Weissman
APOLLO Computer Inc.

;;; -*- Mode: Emacs-Lisp -*-
(defvar mdw:gensym-name "GENSYM")
(defvar mdw:genysm-number 0)
(defmacro mdw:gensym ()
  "Generate a new unused symbol"
  (let (s)
    (while (or (boundp (setq s (intern (format "mdw:%s-%s"
                                               mdw:gensym-name
                                               (setq mdw:gensym-number
                                                     (1+ mdw:gensym-number))))))
               (fboundp s)))
    (list 'quote s)))

(defmacro mdw:add-hooks (function)
  "This macro is called with a symbol representing an emacs lisp
          function.  This function is redefined to funcall a list
          of hooks before and after function execution.
	  This will may lose with complex (interactive) args.
          This will create local-variables as follows:
          mdw:<function-name> bound to the symbol function of function
          mdw:<function-name>-documentation which will be the doc
                string for the function.
          mdw:<function-name>-before-hooks, a list of functions to funcall
                before execution. These functions will be called with the
                same arguments as the original function.
          mdw:<function-name>-after-hooks, a list of functions to funcall
                after execution.  These functions will be called with the
                result of executing the original function followed by the
                original arguments.
          This will take and return the same arguments as the original function.
          "
  (let* ((mdw-name   (concat "mdw:" (symbol-name function)))
         (mdw-before (concat mdw-name "-before-hooks"))
         (mdw-after  (concat mdw-name "-after-hooks"))
         (mdw-doc    (concat mdw-name "-documentation"))
         (args       (mdw:gensym))
         (hook       (mdw:gensym))
         (result     (mdw:gensym)))
    (if (fboundp function)
        (list 'progn
              (list 'defvar (intern mdw-name)
                    (list 'symbol-function (list 'quote function)))
              (list 'defvar (intern mdw-doc)
                    (list 'documentation   (list 'quote function)))
              (list 'defvar (intern mdw-before) nil)
              (list 'defvar (intern mdw-after)  nil)
              (list 'defun function (list '&rest args)
                    (concat
                      (if (boundp (intern mdw-doc))
                          (eval (intern mdw-doc))
                          (documentation function))
                      "\n\nAdded hooks: " mdw-before " &\n"
                      "             " mdw-after ".")
                    '(interactive)
                    (list 'mapcar
                          (list 'function
                                (list 'lambda (list hook)
                                      (list 'apply hook args)))
                          (intern mdw-before))
                    (list 'let
                          (list
                            (list result (list 'apply (intern mdw-name) args)))
                          (list 'mapcar
                                (list 'function (list 'lambda (list hook)
                                                      (list 'apply hook args)))
                                (intern mdw-after))
                          result))))))