2010-11-16 10 views
3

Comment puis-je fournir un module qui nécessite de patcher flymake, avec un minimum de temps de démarrage (= chargement automatique) et un impact minimal sur emacs.el de l'utilisateur?emacs: aidez-moi à résoudre ce problème de commande de chargement automatique avec flymake et csharp

Je travaille sur le module flymake-for-csharp. Il fonctionne avec flymake, lui apprend comment être plus flexible avec les fichiers de code C#. Par exemple, au lieu de simplement utiliser un fichier makefile, flymake-for-csharp peut également utiliser un fichier .csproj ou peut appeler directement csc.exe.

Le module fonctionne correctement. J'essaie maintenant de le charger correctement.

Voici le défi. Pour définir les langues qui font flymake'd, flymake.el inclut une liste d'extensions de fichiers (.java, .cs, .c, etc.) ainsi que les routines init et cleanup pour chacune de ces langues. Il y a une entrée pour C# dans le fichier flymake.el par défaut, mais comme je l'ai dit, le comportement par défaut de C# n'est pas assez flexible. Pour le rendre plus flexible, j'ai besoin de remplacer l'entrée C# dans l'alist de flymake, de sorte qu'elle pointe vers la nouvelle logique init/cleanup dans le module flymake-for-csharp. Ya avec moi?

Il n'y a aucun problème pour patcher l'alist lors de l'exécution. Il ressemble à ceci:

(let (elt 
     (csharp-entry nil) 
     (masks flymake-allowed-file-name-masks)) 

    ;; Find the existing C# entry 
    (while (consp masks) 
     (setq elt (car masks)) 
     (if (string= "\\.cs\\'" (car elt)) 
      (setq csharp-entry elt)) 
     (setq masks (cdr masks))) 

    ;; remove the original entry for C# ... 
    (if csharp-entry 
     (setq flymake-allowed-file-name-masks 
       (delete csharp-entry flymake-allowed-file-name-masks))) 

    ;; Now add a new entry for C#, with the custom init and cleanup methods. 
    (setq flymake-allowed-file-name-masks 
      (cons 
      '("\\.cs\\'" flymake-for-csharp-init flymake-for-csharp-cleanup) 
      flymake-allowed-file-name-masks))) 

La solution à long terme est de convaincre les auteurs de flymake et emacs d'accepter la logique qui est actuellement en flymake-pour-csharp. Alors l'alist obtiendra les routines d'init/cleanup plus flexibles et bob votre oncle.

Mais pour l'instant, je veux que flymake-for-csharp fonctionne avec le flymake.el existant (builtin). Là réside le problème: comment puis-je faire le chargement automatique flymake-for-csharp, tout en patchant encore l'alist?

Idéalement, je voudrais le emacs.el de l'utilisateur à ressembler à ceci:

(autoload 'flymake-for-csharp-init "flymake-for-csharp" nil nil) 

... avec peut-être une petite section (eval-after-load ...

Mais vous voyez, la fonction flymake-for-csharp-init s'appellerait seulement après l'alias flymake est corrigé pour inclure la nouvelle entrée pour C#.

Y a-t-il un moyen de contourner cette situation de la poule et de l'œuf?


une approche que je pensais était d'utiliser (require 'flymake-for-csharp) au lieu de autoload. Dans ce module flymake-for-csharp, exécutez uniquement la logique de patch, puis utilisez le chargement automatique, d'une manière ou d'une autre, pour le reste des fonctions. Serait-ce une bonne idée? Cela exigerait-il que je livre flymake-for-csharp dans deux fichiers distincts?

Une autre approche que je pensais était d'utiliser un eval-after-load sur flymake.el. En cela, je pourrais fournir la fonction de patch. Couple de questions avec ceci:

  • Est-ce que cela ne fonctionnerait que si flymake est chargé automatiquement? Que se passe-t-il avec la logique dans un eval-after-load pour un module qui est déjà chargé lorsque l'eval-after-load (externe) est évalué? Comment est-ce que je ferais ceci sans impact sur le emacs.el de l'utilisateur?


En résumé, Comment puis-je livrer un module qui nécessite rapiéçage flymake, avec le temps de démarrage minimal (= autoload) et un impact minimal sur emacs.el de l'utilisateur?

+0

Aucune idée, mais ce que vous faites semble génial et j'applaudis avec courage. –

Répondre

1

Si je comprends bien, ayant l'utilisateur d'ajouter ceci à leur .emacs résoudrait le problème:

;;;###autoload 
(eval-after-load "flymake" '(code-that-patches-flymake-allowed-file-name-masks)) 
(autoload 'flymake-for-csharp-init "flymake-for-csharp" nil nil) 

Maintenant, si vous travaillez avec les gens en utilisant votre package, vous pouvez utiliser le loaddefs.el trick pour obtenir ce code automatiquement chargé par l'utilisateur en mettant le commentaire ;;;###autoload juste avant la ligne eval-after-load dans votre package, puis reconstruisez le fichier loaddefs.el. Mais, si vous espérez une solution pour une utilisation générale dans les internets, vous avez besoin que l'utilisateur ait les deux lignes .emacs.


Un commentaire sur votre code de nettoyage, je crois qu'il peut être simplifié à:

(let ((csharpentry (assoc "\\.cs\\'" flymake-allowed-file-name-masks))) 
    (when csharpentry 
    (setcdr csharpentry '(flymake-for-csharp-init flymake-for-csharp-cleanup)))) 
+0

Merci, Trey ... – Cheeso

+0

hey, un suivi ... appelons le fn qui corrige l'alist 'flymake-for-csharp-monkeypatch-flymake'. supposons que je fournisse fn dans 'flymake-for-csharp.el', et marquez-le avec' ;;; ### autoload'. Alors, les utilisateurs auraient juste besoin d'inclure une seule ligne, '(eval-after-load" flymake "'(flymake-pour-csharp-monkeypatch-flymake))' dans leurs .emacs? Cela minimiserait l'impact sur .emacs. Cela impliquerait, je pense, de charger le module entier de flymake-for-csharp quand flymake est chargé, alors que votre suggestion retarderait le chargement du module csharp, mais peut-être que c'est ok. Qu'est-ce que tu penses? – Cheeso

+0

@Cheeso Le ';;; ### autoload' ne fonctionne que si vous avez quelque chose construire le fichier' loaddefs.el' (voir le lien dans ma réponse pour 'loaddefs.el trick'.) Donc, si vous avez l'autoload à travailler, alors je crois que vous avez raison. –