Estou escrevendo um modo principal para uma linguagem de programação, mas quero oferecer suporte a versões mais antigas do Emacs. prog-mode
é relativamente novo. Quero herdar de prog-mode
se estiver definido, mas ainda assim fazer algo sensato.
Qual é a melhor abordagem? Devo defalias
prog-mode
no Emacsen mais antigo, ou isso interferirá em outros modos se eles fizerem a mesma coisa?
major-mode
prog-mode
version-compatibilty
Wilfred Hughes
fonte
fonte
prog-mode
. Notavelmente, você sofrerá com a falta de vinculação lexical.Respostas:
À custa de uma ligação extra de símbolo de nível superior, há uma solução muito elegante que evita repetir o
define-derived-mode
formulário:Funciona bem em qualquer Emacs> = 23. Eu vim com isso há
haml-mode
alguns anos atrás, o IIRC, e parece que ele se espalhou de lá para vários outros modos principais. A principal coisa que adefine-derived-mode
macro faz com o símbolo do modo pai é gerar um código que chama sua função: nesse sentido,defalias
torna a nova variável exatamente equivalente à função com alias.Uma ressalva é que isso pode confundir
derived-mode-p
, portanto, o código que verifica se seu modo é derivadoprog-mode
pode não funcionar corretamente. Na prática, não encontrei nenhum problema: é mais comum o uso desse códigoprog-mode-hook
, que ainda é executado.(Como Jorgen aponta nos comentários,
define-derived-mode
também usa amode-class
propriedade do símbolo do modo pai edefalias
não a copia. No momento da redação, esta propriedade parece ser usada apenasspecial-mode
.)Atualização: hoje em dia eu simplesmente sugeriria exigir pelo menos o Emacs 24, já que versões mais antigas são obsoletas há muito tempo.
fonte
prog-mode
, mas não funciona para todos os modos.define-derived-mode
copia amode-class
propriedade do símbolo para o modo filho. Odefalias
vão não transferir essa propriedade. Semode-class
for relevante para o seu caso de uso, você precisará copiá-lo / configurá-lo manualmente.mode-class
propriedade indica.tl; dr: Use
if
e sua própria função init:Em seguida, faça toda a inicialização do modo em
your-cool-init
.Explicação mais longa:
O problema é que a maneira oficial de escrever um modo principal derivado é usar a
define-derived-mode
macro:No Emacsen mais antigo (pré-24), isso quebra quando
prog-mode
. E você não pode usá(if (fboundp 'prog-mode) ...)
-lo porque a macro espera um símbolo literal e o citará na expansão.define-derived-mode
usa o pai de várias maneiras. Você precisaria copiar todos aqueles em sua própria definição de modo para usá-los, e isso é tedioso e propenso a erros.Portanto, a única maneira é usar duas
define-derived-mode
instruções diferentes , dependendo da existênciaprog-mode
ou não. Isso deixa você com o problema de escrever seu código de inicialização duas vezes. O que é obviamente ruim, então você extrai isso para sua própria função, conforme descrito acima.(É claro que a melhor solução é largar o suporte para 23.xe usar o escopo lexical. Mas acho que você já considerou e largou essa opção. :-))
fonte
prog-mode
Emacsen mais antigo? Faria sentido derivartext-mode
oufundamental-mode
seprog-mode
não estiver disponível?fboundp
primeiro, apenas com adefine-derived-mode
declaração? Então o modo atual com definição completa pode ser derivado desse modo intermediário? Dessa forma, o modo inteiro não precisa ser definido duas vezes.fundamental-mode
é equivalente a derivar denil
(e de fatodefine-derived-mode
substituifundamental-mode
pornil
), emboratext-mode
não seja apropriado, pois o código do programa não é texto. A maioria das configurações padrãotext-mode
não faz sentido nos modos de programação fora dos comentários. É por isso queprog-mode
foi introduzido em Emacs 24.define-derived-mode
definições em umif
formulário, apenas para o modo intermediário, em vez do modo final. Você estaria substituindo adefun
função for init por umadefine-derived-mode
para o modo final. Eu não acho que isso seja particularmente preferível. Você também pode definir umprog-mode
você mesmo, como sugere a pergunta original, mas isso pode facilmente confundir outros modos que dependemfboundp
para verificar a presença desse modo.define-derived-mode
declarações diferentes sejam necessárias. Alguns anos atrás, eu vim com a solução que eu publiquei como uma resposta separada, e parece funcionar bem nos Emacs 23 e 24. Código como ele é usado em vários modos populares populares.Eu acho que testar usando
fboundp
faz mais sentido.fonte
Você pode definir uma macro de wrapper para
define-derived-mode
avaliar seus argumentos.(Aviso: apenas minimamente testado.)
fonte