古いemacsenをサポートしながら、prog-modeから継承するにはどうすればよいですか?


10

プログラミング言語のメジャーモードを書いていますが、古いEmacsバージョンをサポートしたいと考えています。prog-mode比較的新しいです。prog-mode定義されている場合は継承したいのですが、それ以外の場合は賢明なことを行います。

最善のアプローチは何ですか?私がすべきdefalias prog-mode古いのEmacsen上、または、彼らは同じことを行う場合には、他のモードと干渉するのだろうか?


Emacs <24のサポートを単に削除することをお勧めします。私の意見では、これ以上努力する価値はありませんprog-mode。特に、字句バインディングの欠如に悩まされます。
lunaryorn 2014年

私はjulia-modeに貢献しており、コアチームの一部は古いEmacsenを使用しており、サポートすることを望んでいます。
Wilfred Hughes

1
@lunaryorn Emacs 24はまだかなり新しいものです。Emacs 23は多くのOSの現在のバージョンです。Emacs 22はまだいくつか最新のものです。誰もが狂ったようにソフトウェアをアップグレードするわけではありません。Emacs 23のサポートをやめると、最先端を切望する少数のユーザーに制限されます。
Gilles「SO-邪悪なことをやめなさい」

1
古いEmacsバージョンを使用する理由はたくさんあります。たとえば、Windowsでは、Emacs 23が非常に遅くなったため、Emacs 22を使用することにしました。
Lindydancer 2014年

@ギレス私はそれが単なる「少数のユーザー」であるとは思えません。Flycheckは、そもそもEmacs 23をサポートしたことがなく、それでもMELPAで最も人気のあるパッケージの1つになりました…
lunaryorn 14年

回答:


11

追加のトップレベルシンボルバインディングを犠牲にして、define-derived-modeフォームの繰り返しを回避する非常にきちんとしたソリューションがあります。

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

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

23以上のすべてのEmacsでhaml-mode正常に動作します。数年前にIIRC でこれを思いつきましたが、そこから他のいくつかの主要なモードに広がったようです。define-derived-modeマクロが親モードシンボルで行う主なことは、その関数を呼び出すコードを生成することです。この意味でdefalias、新しい変数はエイリアス関数とまったく同じになります。

1つの注意点は、これが混乱derived-mode-pするprog-mode可能性があることです。そのため、モードの派生元かどうかを確認するコードは正しく機能しない可能性があります。実際には問題は発生していません。そのようなコードがにフックするのがより一般的ですがprog-mode-hook、それでも実行されます。

(ヨルゲンはコメントで指摘するように、define-derived-modeまた、使用するmode-class親モードシンボルからプロパティを、そしてdefaliasそれをコピーしません。書いている時点では、このプロパティはのみのために使われているようですspecial-mode。)

更新:最近のバージョンでは、Emacs 24以上を要求することをお勧めします。古いバージョンは古くなっているためです。


2
素敵な解決策!prog-modeただし、これはで機能しますが、すべてのモードで機能するとは限りません。シンボルプロパティを子モードにdefine-derived-modeコピーしmode-classます。defaliasではない、このプロパティを転送します。mode-classユースケースに関連する場合は、手動でコピー/設定する必要があります。
JorgenSchäfer2014年

それを理解してくれてありがとうmode-class
sanityinc 2014年

3

tl; dr:if独自のinit関数を使用します。

(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)))

次に、すべてのモードの初期化をで行いyour-cool-initます。

より長い説明:

問題は、派生したメジャーモードを書く公式な方法はdefine-derived-modeマクロを使用することです。

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

古いEmacsen(24より前)では、これはで壊れprog-modeます。そして(if (fboundp 'prog-mode) ...)、マクロはリテラルシンボルを期待し、展開でそれを引用するため、そこでは使用できません。

define-derived-mode親をさまざまな方法で使用します。あなたはそれらを利用するためにあなた自身のモード定義でそれらすべてをコピーする必要があるでしょう、そしてそれは面倒でエラーを起こしやすいものです。

したがって、唯一の方法はdefine-derived-modeprog-mode存在するかどうかに応じて、2つの異なるステートメントを使用することです。これにより、初期化コードを2回記述する問題が残ります。もちろんこれは悪いことなので、上記のようにそれを独自の関数に抽出します。

(もちろん、23.xのサポートを削除して字句スコープを使用するのが最善の解決策です。しかし、そのオプションをすでに検討して削除していると思います。:-))


prog-mode古いEmacsenで最も近いものは何ですか?ですが、それが由来すると意味をなさないtext-modefundamental-modeあればprog-mode利用できないのですか?
Wilfred Hughes

@Jorgenまたはfboundpdefine-derived-modeステートメントだけで、first を使用して中間モードを導出できますか?次に、完全な定義を持つ実際のモードは、その中間モードから導出できますか?これにより、モード全体を2回定義する必要がなくなります。
Kaushal Modi 2014

1
@WilfredHughes、ありません。由来のfundamental-mode由来のと等価であるnil(実際、define-derived-mode置き換えfundamental-modeを有するnil)、一方では、text-modeプログラムコードがテキストではないように、適切ではありません。のデフォルト設定のほとんどは、text-modeコメント以外のプログラミングモードでは意味がありません。これはなぜあるprog-modeのEmacs 24で導入されました
ヨルゲン・シェーファー

@kaushalmodi、中間モードを派生させることもできますが、最終モードではなく中間モードのためだけdefine-derived-modeに、ifフォームに2つの定義が必要になります。defuninit関数のdefine-derived-modeforをfinalモードのaに置き換えます。これは特に好ましいとは思いません。prog-mode元の質問が示唆しているように、自分自身を定義することもできますがfboundp、そのモードの存在の確認に依存している他のモードを簡単に混乱させる可能性があります。
JorgenSchäfer2014年

2つの異なるdefine-derived-modeステートメントが必要だとは思いません。数年前に別の回答として投稿したソリューションを思いつきましたが、Emacs 23とEmacs 24の両方で正常に動作するようです。このようなコードは、いくつかの一般的な主要モードで使用されています。
sanityinc 2014年


0

define-derived-mode引数を評価するためのラッパーマクロを定義できます。

(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))

(警告:最小限のテストのみ。)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.