OVH Cloud OVH Cloud

defadvice et fonctions interactive

3 réponses
Avatar
Oursoye
Salut,

La fonction "timeclock-out" a un fonctionnement
specifique en mode interactif.

Si on ajoute un advice, par exemple
(defadvice timeclock-out (after planner-timeclock activate)
"Clear `planner-timeclock-current-task.'"
(setq planner-timeclock-current-task nil))
qui est dans le module planner-timeclock, alors
la fonction timeclock-out n'est jamais reconnu comme
une fonction interactive, même lorsqu'elle est lancée
en mode interactif. Dit autrement, la fonction
(interactive-p) située dans timeclock-out renvoie nil,
alors que l'appel est interactif.

Pourquoi ? Comment corriger pour que l'appel interactif
de timeclock-out soit correctement reconnu ?

Merci.
O.

3 réponses

Avatar
Florent Georges
Oursoye wrote:

la fonction timeclock-out n'est jamais reconnu comme
une fonction interactive, même lorsqu'elle est lancée
en mode interactif. Dit autrement, la fonction
(interactive-p) située dans timeclock-out renvoie nil,
alors que l'appel est interactif.



D'après la docstring de 'interactive-p', il s'agit d'un mauvais
emploi de la fonction. Extrait et essai correction (ode
non-testé !) :

;; `interactive-p' docstring excerpt:
;;
;; The only known proper use of `interactive-p' is in deciding
;; whether to display a helpful message, or how to display it. If
;; you're thinking of using it for any other purpose, it is quite
;; likely that you're making a mistake. Think: what do you want
;; to do when the command is called from a keyboard macro?
;;
;; If you want to test whether your function was called with
;; `call-interactively', the way to do that is by adding an extra
;; optional argument, and making the `interactive' spec specify
;; non-nil unconditionally for that argument. (`p' is a good way
;; to do this.)

(defun timeclock-out (&optional arg reason find-reason
interactivep)
"Clock out, recording the current time moment in the timelog.
If a prefix ARG is given, the user has completed the project
that was begun during the last time segment.

REASON is the user's reason for clocking out. If REASON is
nil, and FIND-REASON is non-nil -- or the user calls
`timeclock-out' interactively -- call the function
`timeclock-get-reason-function' to discover the reason.

INTERACTIVEP should never be set manually. It is designed to
be set automaticaly while interactive call."
(interactive "Pnininp")
(or timeclock-last-event
(error "You haven't clocked in!"))
(if (equal (downcase (car timeclock-last-event)) "o")
(error "You've already clocked out!")
(timeclock-log
(if arg "O" "o")
(or reason
(and timeclock-get-reason-function
(or find-reason interactivep)
(funcall timeclock-get-reason-function))))
(run-hooks 'timeclock-out-hook)
(if arg
(run-hooks 'timeclock-done-hook))))

Pour expliquer ce comportement, voici un exemple de ce qui ce
passe lors de la définition d'un advice :

ELISP> (defadvice load (before drkm-misc:ad-load activate)
"Affiche toujours un message lors d'un `load()'."
(ad-set-arg 2 nil))
load
ELISP> (symbol-function 'load)
(lambda
(file &optional noerror nomessage nosuffix must-suffix)
"$ad-doc: load$"
(let
(ad-return-value)
(setq nomessage nil)
(setq ad-return-value
(ad-Orig-load
file noerror nomessage nosuffix must-suffix))
ad-return-value))

ELISP> (symbol-function 'ad-Orig-load)
#<subr load>
ELISP>

On voit que la fonction initiale ne fait plus partie de la
fontion directement appellée par l'utilisateur (ou autre) mais
est à son tour appelée par cette dernière. Donc 'interactive-p'
renvoit correctcement nil.

--drkm
Avatar
laurentcommercial
Extrait et essai correction (ode
non-testé !) :



Ca marche nickel chrome. Merci.

O
Avatar
Florent Georges
wrote:

>Extrait et essai correction (ode
>non-testé !) :

Ca marche nickel chrome. Merci.



Qu'as-tu fait exactement ? Si tu as modife la definition de
'timeclock-out', as-tu rapporte le "bug" ?

--drkm