Elisp est un langage interprété. Vous pouvez mettre du code spécifique à la version dans votre .emacs
, mais le protéger en testant au moment du chargement qu'il fonctionne sur la bonne version.
(if (is-new-feature-available)
(shiny-new-feature)
(old-less-nifty-feature))
Ce code fonctionnera dans toutes les versions car il (shiny-new-feature)
n'est évalué que lorsqu'il (is-new-feature-available)
renvoie true. Une grande partie de cette réponse est consacrée à la mise en œuvre (is-new-feature-available)
.
Faire face à différents ensembles de fonctionnalités
Il vaut mieux tester si une fonctionnalité est disponible que de tester la version Emacs. Parfois, la fonctionnalité peut être disponible en tant que package facultatif. Si vous souhaitez exécuter du code dans XEmacs ou une autre variante d'Emacs, il se peut qu'il ait acquis les mêmes fonctionnalités dans différentes versions. Utilisez la fonction boundp
pour tester si une variable est disponible et fboundp
pour tester si une fonction est disponible.
Par exemple, l'extrait de code suivant lie une clé pour basculer visual-line-mode
si elle est disponible, et longlines-mode
sinon.
(global-set-key "\eml" (if (fboundp 'visual-line-mode)
'visual-line-mode
'longlines-mode))
Parfois, plutôt que de tester la fonctionnalité, il est plus facile d'exécuter un petit morceau de code et d' ignorer les erreurs dues à des fonctions non définies, des arguments invalides, etc. Ne faites pas cela pour de grandes quantités de code, car cela rendra votre code très difficile à déboguer.
Par exemple, je ne veux pas voir de barre d'outils. Les anciennes versions d'Emacs n'en avaient pas du tout. GNU Emacs et XEmacs ont ajouté cette fonctionnalité de différentes manières et en ont fait la valeur par défaut. Voici comment je les désactive. La set-specifier
fonction est spécifique à XEmacs et default-toolbar-visible-p
est spécifique aux versions assez récentes d'Emacs; l'utilisation condition-case
prend en charge les deux exigences. GNU Emacs fournit une fonction dédiée donc je teste simplement si cette fonction est disponible.
;; For XEmacs
(condition-case nil
(set-specifier default-toolbar-visible-p nil)
(error nil))
;; For GNU Emacs
(if (fboundp 'tool-bar-mode)
(tool-bar-mode 0))
Certains noms de visage changent au fil des versions. Utilisez facep
pour tester la disponibilité d'un nom de visage.
(let ((face (if (facep 'mode-line) 'mode-line 'modeline)))
(set-face-background face …))
Parfois, vous souhaiterez peut-être charger un joli package s'il est présent et ne rien faire si le package n'est pas disponible. require
a un argument facultatif pour cela.
(require 'tex-site nil t) ;; Load AUCTeX if available
Cet argument a été introduit dans GNU Emacs 20.4 et n'est pas disponible dans XEmacs, donc si vous voulez remonter aussi loin, vous devrez soit l'enrouler condition-case
soit l'utiliser à la load
place (ce qui ne vérifie pas les bibliothèques déjà chargées) .
Limitez les dépendances de version aux fonctionnalités de niveau utilisateur. N'utilisez pas de nouvelles fonctionnalités de programmation qui ne sont pas disponibles dans toutes les versions que vous souhaitez prendre en charge: vous devrez fournir une version de compatibilité pour les anciennes versions, et il est plus facile de maintenir une seule version.
Parfois, vous avez besoin d'une fonctionnalité à de nombreux endroits, et elle est disponible sur toutes les implémentations qui vous intéressent, mais d'une manière différente. C'est surtout le cas si vous voulez prendre en charge à la fois XEmacs et GNU Emacs: ils avaient une tendance frustrante à se copier les fonctionnalités les uns des autres mais pas leur interface. Dans ce cas, la définition d'une fonction de compatibilité est plus pratique que le test au point d'utilisation.
Par exemple, le code suivant définit une fonction qui renvoie le système de fenêtres du cadre actuel, la méthode GNU moderne, la méthode XEmacs moderne et la méthode à l'ancienne lorsque vous ne pouviez pas combiner des cadres de terminal et d'interface graphique dans la même instance.
(defalias 'compat-window-system
(cond
((fboundp 'window-system) #'window-system)
((fboundp 'device-type)
(lambda (&optional frame)
(device-type (frame-device frame))))
(t
(lambda (&optional frame) window-system))))
Dépendances de l'environnement
Il n'y a pas beaucoup de code qui doit dépendre de la plate-forme. La variable system-type
indique le système d'exploitation. Je l'utilise exclusivement pour activer quelques hacks pour ms-dos
(oui, mes fichiers sont aussi anciens) et windows-nt
.
Vous voudrez peut-être ajouter des répertoires à votre chemin de recherche exécutable ( PATH
), mais il est généralement préférable de le faire en dehors d'Emacs, dans votre .profile
système de type Unix et via le panneau de configuration de Windows. Pour tester si un programme externe est disponible, appelez executable-find
.
Pour le code qui doit agir différemment selon le type d'interface graphique, le cas échéant, cochez window-type
ou ses successeurs (voir ci-dessus).
Fichiers d'initialisation
Pour une compatibilité maximale, insérez votre code ~/.emacs
. GNU Emacs a commencé à chercher dans la ~/emacs.d
version 22. XEmacs a commencé à chercher ~/.xemacs
dans la version 21.4. Une autre approche consiste à mettre du code de compatibilité ~/.emacs
et à terminer en chargeant votre fichier principal. Mettez (setq load-home-init-file t)
quelque part pour éviter que les versions récentes¹ de XEmacs ne vous demandent si vous souhaitez déplacer votre .emacs
emplacement XEmacs uniquement.
Différentes versions d'Emacs peuvent avoir une extension différente et incompatible pour certaines macros. Ne partagez donc pas vos fichiers compilés en octets entre les versions, compilez les fichiers sur chaque machine.
Parfois, une fonctionnalité est obsolète, mais vous souhaitez toujours l'utiliser car c'est tout ce qu'il y a dans une autre version que vous souhaitez prendre en charge. Les avertissements du compilateur d'octets proviennent de la byte-obsolete-variable
propriété.
(cond
((not (boundp 'desktop-enable))
(defvaralias 'desktop-enable 'desktop-save-mode))
((get 'desktop-enable 'byte-obsolete-variable)
(put 'desktop-enable 'byte-obsolete-variable nil)))
¹ Relativement parlant, par rapport aux XEmac plus anciens.
window-system
, etc. peuvent être raisonnablement répondues ici.