emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: table.el


From: Tak Ota
Subject: Re: table.el
Date: Sun, 02 Dec 2001 18:16:31 -0800 (PST)

Sun, 02 Dec 2001 16:16:40 -0500: "Stefan Monnier" <monnier+gnu/address@hidden> 
wrote:

> > > But I'd still advocate for passing not just the arguments but the
> > > function itself so that the same wrapper-hook can be used for
> > > several functions.  This is obviously a bit more difficult to do
> > > since the macro doesn't know from where it's being called.
> > 
> > I think it is a good idea.  How about the following definition?  The
> > argument to backtrace-frame depends on run-time environment.  1 is
> > good when it is byte-compiled.
> 
> I think this is too brittle since it only works with byte-compilation.
> Also I'm not sure what to think about inhibit-wrapper-hook: there is no
> such thing for `run-hooks', so wy should it be needed for wrapper-hooks ?
> 
> How about
> 
>       (defmacro with-wrapper-hook (wrapper-form &rest body)
>         (let ((wrapper-var (car wrapper-form))
>               (fun-sym (make-symbol "wrapped-fun")))
>           `(let ((,fun-sym
>                  ;; Make the body into a function so we can pass it
>                  ;; to the wrapper-hook.
>                  (lambda ,(cdr wrapper-form)
>                    (if ,wrapper-var
>                        (let ((,wrapper-var ,wrapper-var))
>                          ;; Hooks can also contain a non-list.
>                          (unless (consp ,wrapper-var)
>                            (setq ,wrapper-var (list ,wrapper-var)))
>                          ;; Local/global special handling.
>                          (when (and (local-variable-p ',wrapper-var)
>                                     (eq t (car ,wrapper-var)))
>                            (setq ,wrapper-var
>                                  (append (default-value ',wrapper-var)
>                                          (cdr ,wrapper-var))))
>                          ;; Call the first wrapper, with function and args.
>                          (funcall (pop ,wrapper-var)
>                                   ,fun-sym ,@(cdr wrapper-form)))
>                      ,@body))))
>              (funcall ,fun-sym ,@(cdr wrapper-form)))))

I tried this but I get lambda expression for the function instead of
symbol name.  BTW the next one took a few of good things from your
implementation and removed the previous byte compile restriction.
Also inhibit-wrapper-hook is removed.  What do you think?

(defmacro with-wrapper-hook (wrapper-form &rest body)
  "Invoke wrappers in WRAPPERS-VAR if present, otherwise execute forms in BODY.
WRAPPER-FORM looks like (WRAPPERS-VAR ARG...), where ARG... is the
list of arguments passed to each wrapper in list stored in
WRAPPERS-VAR.  Each wrapper receives a symbol of the original function
as the first argument followed by ARG...  All wrappers must call the
original function from within itself.  While this macro is calling
each wrapper, WRAPPERS-VAR is bound to the cdr of the list, so that
recursive invocations of `with-wrappers' on the same variable will
result in each wrapper in the list being called.  Use `add-hook' and
`remove-hook' for manipuation of WRAPPERS-VAR.

An example usage of this is:

  (defvar kill-region-wrapper-hook nil)

  (defun kill-region (beg end)
    (with-wrapper-hook (kill-region-wrapper-hook beg end)
      ...ordinary kill-region stuff...))

  (defun my-wrapper (func beg end)
    (cond
     ((eq func (function kill-region))
      (let ((offset 5))
        (funcall func (+ beg offset) (+ end offset))))
     (t (funcall func beg end))))

  (add-hook 'kill-region-wrapper-hook (function my-wrapper))"

  (let ((wrapper-var (car wrapper-form)))
    `(if ,wrapper-var
         (let ((,wrapper-var ,wrapper-var))
           ;; Hooks can also contain a non-list.
           (unless (consp ,wrapper-var)
             (setq ,wrapper-var (list ,wrapper-var)))
           ;; Local/global special handling.
           (when (and (local-variable-p ',wrapper-var)
                      (eq t (car ,wrapper-var)))
             (setq ,wrapper-var
                   (append (default-value ',wrapper-var)
                           (cdr ,wrapper-var))))
           ;; Call the first wrapper, with function and args.
           (funcall (pop ,wrapper-var)
                    (nth 1 (backtrace-frame
                            (if (eq (nth 1 (eval-when-compile (backtrace-frame 
1))) 'progn) 7 1)))
                    ,@(cdr wrapper-form)))
       ,@body)))

-Tak



reply via email to

[Prev in Thread] Current Thread [Next in Thread]