J'écris un mode majeur pour un langage de programmation, mais je veux prendre en charge les anciennes versions d'Emacs. prog-mode
est relativement nouveau. Je veux hériter de prog-mode
si c'est défini, mais toujours faire quelque chose de sensé autrement.
Quelle est la meilleure approche? Dois-je defalias
prog-mode
utiliser un Emacsen plus ancien, ou cela interférera-t-il avec d'autres modes s'ils font la même chose?
major-mode
prog-mode
version-compatibilty
Wilfred Hughes
la source
la source
prog-mode
. Notamment, vous souffrirez du manque de liaison lexicale.Réponses:
Au prix d'une liaison de symboles de niveau supérieur supplémentaire, il existe une solution très soignée qui évite de répéter le
define-derived-mode
formulaire:Fonctionne très bien dans n'importe quel Emacs> = 23. J'ai proposé cela
haml-mode
il y a quelques années à l'IIRC, et il semble s'être propagé de là à plusieurs autres modes majeurs. La principale chose que ladefine-derived-mode
macro fait avec le symbole du mode parent est de générer du code qui appelle sa fonction: dans ce sens,defalias
rend la nouvelle variable exactement équivalente à la fonction aliasée.Une mise en garde est que cela peut prêter à confusion
derived-mode-p
, donc le code qui vérifie si votre mode est dérivéprog-mode
peut ne pas fonctionner correctement. En pratique, je n'ai rencontré aucun problème: il est plus courant qu'un tel code s'y accrocheprog-mode-hook
, qui est toujours exécuté.(Comme Jorgen le souligne dans les commentaires,
define-derived-mode
utilise également lamode-class
propriété du symbole du mode parent etdefalias
ne la copiera pas. Au moment de la rédaction, cette propriété ne semble être utilisée que pourspecial-mode
.)Mise à jour: ces jours-ci, je suggère simplement d'exiger au moins Emacs 24, car les anciennes versions sont obsolètes depuis longtemps.
la source
prog-mode
, mais ne fonctionnera pas pour tous les modes.define-derived-mode
copie lamode-class
propriété de symbole dans le mode enfant. Ledefalias
va pas transférer cette propriété. Si celamode-class
correspond à votre cas d'utilisation, vous devez le copier / définir manuellement.mode-class
propriété dénote.tl; dr: utilisez
if
et votre propre fonction init:Effectuez ensuite toute l'initialisation du mode
your-cool-init
.Explication plus longue:
Le problème est que la manière officielle d'écrire un mode majeur dérivé est d'utiliser la
define-derived-mode
macro:Sur les anciens Emacsen (pré-24), cela se brise quand
prog-mode
. Et vous ne pouvez pas l'utiliser(if (fboundp 'prog-mode) ...)
parce que la macro attend un symbole littéral et le citera pour vous dans l'extension.define-derived-mode
utilise le parent de multiples façons. Vous devez copier tous ceux-ci dans votre propre définition de mode pour les utiliser, et c'est à la fois fastidieux et sujet aux erreurs.La seule façon est donc d'utiliser deux
define-derived-mode
instructions différentes , selon qu'ellesprog-mode
existent ou non. Cela vous pose le problème d'écrire deux fois votre code d'initialisation. Ce qui est bien sûr mauvais, alors vous extrayez cela dans sa propre fonction, comme décrit ci-dessus.(La meilleure solution est bien sûr de supprimer le support pour 23.x et d'utiliser la portée lexicale. Mais je suppose que vous avez déjà envisagé et abandonné cette option. :-))
la source
prog-mode
Emacsen plus ancien? Serait-il sensé de dérivertext-mode
oufundamental-mode
s'ilprog-mode
n'est pas disponible?fboundp
abord, avec juste l'define-derived-mode
instruction? Ensuite, le mode réel avec définition complète peut être dérivé de ce mode intermédiaire? De cette façon, le mode entier n'a pas à être défini deux fois.fundamental-mode
équivaut à dériver denil
(et en fait,define-derived-mode
remplacefundamental-mode
parnil
), bien qu'iltext-mode
ne soit pas approprié, car le code de programme n'est pas du texte. La plupart des paramètres par défaut danstext-mode
n'ont pas de sens dans les modes de programmation en dehors des commentaires. C'est pourquoi aprog-mode
été introduit dans Emacs 24.define-derived-mode
définitions dans unif
formulaire, juste pour le mode intermédiaire au lieu du mode final. Vous remplaceriez ledefun
pour la fonction init par undefine-derived-mode
pour le mode final. Je ne pense pas que ce soit particulièrement préférable. Vous pouvez également définir unprog-mode
vous - même, comme le suggère la question d'origine, mais cela peut facilement confondre d'autres modes qui comptentfboundp
pour vérifier la présence de ce mode.define-derived-mode
déclarations différentes soient nécessaires. Il y a quelques années, j'ai trouvé la solution que j'ai publiée en tant que réponse distincte, et cela semble fonctionner correctement dans les deux Emacs 23 et 24. Code comme il est utilisé dans un certain nombre de modes principaux populaires.Je pense que les tests utilisant ont
fboundp
plus de sens.la source
Vous pouvez définir une macro wrapper pour
define-derived-mode
évaluer ses arguments.(Avertissement: seulement testé de manière minimale.)
la source