2010-06-19 3 views
4

J'essayais de répondre à another SO question quand j'ai rencontré un comportement très étrange. Voilà mon petit cas de test:Comment conseiller des primitives dans Emacs

(make-variable-buffer-local 
(defvar my-override-mode-on-save nil 
    "Can be set to automatically ignore read-only mode of a file when saving.")) 

(defadvice file-writable-p (around my-overide-file-writeable-p act) 
    "override file-writable-p if `my-override-mode-on-save' is set." 
    (or 
    my-override-mode-on-save 
    ad-do-it)) 

(defun my-override-toggle-read-only() 
    "Toggle buffer's read-only status, keeping `my-override-mode-on-save' in sync." 
    (interactive) 
    (setq my-override-mode-on-save (not my-override-mode-on-save)) 
    (toggle-read-only)) 

(defun tester-fn() 
    (interactive) 
    (let ((xxx (file-writable-p "/tmp/foofoo")) 
     (yyy (file-writable-p "/tmp/fooxxfoo"))) 
    (message (concat "XXX: " (if xxx "yes" "no") " - YYY: " (if yyy "yes" "no"))))) 

où:.

  • /tmp/foofoo est un fichier en lecture seule que je l'ai visité et courir my-override-toggle-read-only dans
  • /tmp/fooxxfoo n'existe pas.
  • /tmp est accessible en écriture pour l'utilisateur auquel je suis connecté.

Si je lance tester-fn dans un tampon où my-override-mode-on-save est réglé sur t puis-je obtenir un résultat inattendu: XXX: no - YYY: no. Si je cours tester-fn alors que dans un autre tampon (par exemple zéro) j'obtiens la réponse attendue dans le mini-tampon: XXX: no - YYY: yes. Suivre le conseil à travers le débogueur montre qu'il fait exactement ce que je pense qu'il devrait faire, en exécutant les parties auxquelles je m'attends, en sautant les parties auxquelles je m'attends, en retournant la valeur à laquelle je m'attendais. Cependant, le suivi tester-fn à travers le débogueur montre des valeurs très différentes renvoyées (nil & t si la variable évalue comme nul, nil & nil si la variable évalue comme non-nul). Le nil & nil retour est vraiment ce que je trouve bizarre.

Je n'ai aucune idée de ce qui se passe ici. Quelqu'un sait pourquoi je n'obtiens pas les résultats que j'attends?

Répondre

4

Votre code semble bon, à l'exception de la clé manquante. Vous devez définir la valeur de retour de façon appropriée:

(defadvice file-writable-p (around my-overide-file-writeable-p act) 
    "override file-writable-p if `my-override-mode-on-save' is set." 
    (setq ad-return-value 
     (or 
     my-override-mode-on-save 
     ad-do-it))) 

Ceci est documenté dans le advice manual.

+0

J'ai toujours pensé que 'ad-return-value' était utilisé pour remplacer la valeur de retour, et non le définir (et le manuel en dit autant). Mais c'était en effet la pièce manquante - merci! –

+0

@JoeCasadonte Je suppose que j'ai lu ces instructions comme étant les mêmes ... –

+0

la différence (pour moi) est l'hypothèse que la valeur de retour sera normale (c.-à-d. La dernière expression évaluée) et 'ad-return-value' pour changer cela. –

Questions connexes