Eski emacsen'i desteklerken prog modundan nasıl miras alabilirim?


10

Bir programlama dili için büyük bir mod yazıyorum, ancak eski Emacs sürümlerini desteklemek istiyorum. prog-modenispeten yenidir. prog-modeTanımlanmışsa devralmak istiyorum , ama yine de aksi takdirde mantıklı bir şey yapmak istiyorum.

En iyi yaklaşım nedir? Daha defalias prog-modeeski Emacsen'de olmalı mıyım yoksa aynı şeyi yaparlarsa diğer modlara müdahale eder mi?


Ben sadece Emacs <24 için destek bırakmanızı tavsiye ederim prog-mode. Özellikle, sözcüksel bağlanma eksikliğinden muzdarip olacaksınız.
lunaryorn

Julia moduna katkıda bulunuyorum ve bazı çekirdek takımlar eski Emacsen kullanıyor ve bunu desteklememizi tercih ediyorlar.
Wilfred Hughes

1
@lunaryorn Emacs 24 hala oldukça yeni. Emacs 23 birçok işletim sistemindeki geçerli sürümdür. Emacs 22 hala birkaç tanesinde güncel. Herkes yazılımlarını deli gibi yükseltmez. Emacs 23 için düşürme desteği, sizi kanayan kenarı isteyen birkaç kullanıcıyla sınırlar.
Gilles 'SO- kötü olmayı bırak

1
Eski Emacs sürümlerini kullanmanın birçok nedeni vardır. Örneğin, Windows'ta Emacs 23 gerçekten durgunlaştı, bu yüzden orada Emacs 22'ye bağlı kalmayı seçtim.
Lindydancer

@Gilles Sadece bir "az kullanıcı" olduğundan şüphe ediyorum. Flycheck ilk etapta Emacs 23'ü asla desteklemedi ve yine de MELPA'nın en popüler paketlerinden biri oldu…
lunaryorn

Yanıtlar:


11

Ekstra üst düzey bir sembol bağlama pahasına, define-derived-modeformun tekrarlanmasını önleyen çok düzgün bir çözüm var :

(defalias 'my-fancy-parent-mode
  (if (fboundp 'prog-mode) 'prog-mode 'fundamental-mode))

(define-derived-mode my-fancy-mode my-fancy-parent-mode
   ...)

Herhangi bir Emacs> = 23 iyi çalışıyor. haml-modeBirkaç yıl önce IIRC ile bu geldi ve oradan diğer bazı büyük modlara yayılmış gibi görünüyor. define-derived-modeMakronun üst mod sembolü ile yaptığı en önemli şey, işlevini çağıran kod üretmektir: bu anlamda defaliasyeni değişkeni diğer adla işlevle tam olarak eşdeğer yapar.

Bir uyarı, bunun kafa karıştırıcı olabileceğinden derived-mode-p, modunuzun türetildiğini kontrol eden kod prog-modedoğru çalışmayabilir. Uygulamada herhangi bir sorunla karşılaşmadım: böyle bir kodun takılması daha normaldir prog-mode-hook, ki bu hala çalıştırılır.

(Jorgen'in yorumlarda belirttiği gibi, özelliği üst mod simgesinden define-derived-modede kullanır ve kopyalamaz. Yazma sırasında bu özellik yalnızca kullanılmış gibi görünür .)mode-classdefaliasspecial-mode

Güncelleme: Bu günlerde, en azından Emacs 24'e ihtiyaç duymanızı öneririm, çünkü eski sürümler çok eski.


2
Güzel çözüm! Sadece bir uyarı: Bu çalışır prog-mode, ancak her mod için çalışmaz. symbol özelliğini alt moda define-derived-modekopyalar mode-class. defaliasOlacak değil bu özelliği aktarın. Eğer mode-classkullanımı durumda alakalı, bunu elle ayarlamak / kopyalamanız gerekir.
Jorgen Schäfer

Bunu yakaladığınız için teşekkürler, Jorgen - Etrafı kazıp mode-classmülkün neyi ifade ettiği hakkında daha fazla şey öğrenmem gerekecek .
sanityinc

3

tl; dr: ifKendi başlangıç ​​işlevinizi kullanın :

(if (fboundp 'prog-mode)
    (define-derived-mode your-cool-mode prog-mode "Cool"
      "Docstring"
      (your-cool--init))
  (define-derived-mode your-cool-mode nil "Cool"
    "Docstring"
    (your-cool--init)))

Sonra tüm modun başlatılmasını yapın your-cool-init.

Daha uzun açıklama:

Sorun, türetilmiş bir ana mod yazmanın resmi yolunun define-derived-modemakroyu kullanmaktır :

(define-derived-mode your-cool-mode prog-mode ...)

Daha eski Emacsen'de (24 öncesi), bu ne zaman kırılır prog-mode. Ve (if (fboundp 'prog-mode) ...)orada kullanamazsınız çünkü makro değişmez bir sembol bekler ve genişletmede sizin için teklif verir.

define-derived-modeebeveynleri çok çeşitli şekillerde kullanır. Bunları kullanmak için hepsini kendi mod tanımınızda kopyalamanız gerekir ve bu hem sıkıcı hem de hataya açıktır.

Dolayısıyla tek yol, var define-derived-modeolup olmamasına bağlı olarak iki farklı ifade kullanmaktır prog-mode. Bu, başlatma kodunuzu iki kez yazma sorunu yaşamanıza neden olur. Tabii ki kötü, bu yüzden bunu yukarıda açıklandığı gibi kendi işlevine çıkarıyorsunuz.

(Tabii ki en iyi çözüm 23.x için destek bırakmak ve sözlük kapsamını kullanmaktır. Ama sanırım bu seçeneği zaten düşündünüz ve bıraktınız. :-))


prog-modeEski Emacsen'de en yakın eşdeğer nedir? Elde etmek text-modeveya mevcut fundamental-modedeğilse elde etmek mantıklı prog-modemıdır?
Wilfred Hughes

@Jorgen Ya da fboundpsadece define-derived-modeifadeyi kullanarak ilk önce bir ara mod türetebilir miyiz ? O zaman tam tanım ile gerçek mod o ara moddan türetilebilir mi? Bu şekilde tüm modun iki kez tanımlanması gerekmez.
Kaushal Modi

1
@WilfredHughes, hiç yok. Yola çıkarak fundamental-modeelde edilen ile eşdeğerdir nil(ve aslında define-derived-modeyerine geçer fundamental-modeile nilise,) text-modeProgram kodu kısa değil gibi, uygun değildir. Varsayılan ayarların çoğu, text-modeyorumlar dışındaki programlama modlarında anlamlı değildir. Bu nedenle prog-modeEmacs 24'te tanıtıldı.
Jorgen Schäfer

@kaushalmodi, bir ara mod türetebilirsiniz, ancak bu hala son mod yerine ara mod için define-derived-modebir ifformda iki tanım gerektirir . defunİnit işlevini define-derived-modeson mod için a ile değiştiriyor olacaksınız . Bunun özellikle tercih edildiğini düşünmüyorum. prog-modeKendinizi, orijinal sorunun öne sürdüğü gibi tanımlayabilirsiniz , ancak bu modun fboundpvarlığını kontrol etmeye güvenen diğer modları kolayca karıştırabilir .
Jorgen Schäfer

İki farklı define-derived-modeifadenin gerekli olduğuna inanmıyorum . Birkaç yıl önce ayrı bir cevap olarak gönderdiğim çözümü buldum ve her iki Emacs 23 & 24'de de işe yarıyor gibi görünüyor. Kod, bir dizi popüler ana modda kullanıldığı gibi.
sanityinc

0

Bence kullanarak test fboundpyapmak daha mantıklı.

(if (fboundp 'prog-mode)
    ...
   ...)

0

Bağımsız define-derived-modedeğişkenlerini değerlendiren bir sarıcı makro tanımlayabilirsiniz .

(defmacro define-derived-mode* (child parent name &optional docstring &rest body)
  (macroexpand `(define-derived-mode ,(eval child) ,(eval parent) ,(eval name)
                                     ,(eval docstring) . ,body)))
(define-derived-mode* 'toy-mode
  (if (fboundp 'prog-mode) 'prog-mode 'fundamental-mode)
  "Toy"
  "Major mode for my favorite toy language"
  (toy-mode-setup))

(Uyarı: yalnızca minimum düzeyde test edilmiştir.)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.