ポータブルElispの作成


8

理想的には、.emacs.dディレクトリのコンテンツ全体を保存し、ロードしたEmacsで「そのまま」機能させながら、GUIウィンドウシステムなどの特定の環境の機能を利用したいのです。

互換性のない機能の百科事典を探しているのではありません。機能、OS、バージョン、グラフィックスなどを確認する方法と、他の構成のコードを壊さずにこれらを利用する方法を知りたいのですが。

プラットフォームを活用しながら、一般に普及しているEmacsの複数のバージョン(22.x +など)および複数の基盤となるプラットフォーム(OSX、Linux、Windows、その他の* nixなど)で機能するElispを作成するために使用できる基本的なテクニックおよび該当する場合はバージョン固有の機能?


1
@Malabarba質問が「異なるバージョンとプラットフォーム間のすべての違いをリストアップする」と解釈される場合、はい、それは非常に広範です。ただし、基本的な手法(識別子がバインドされているかどうかのテストwindow-system、エラーからの回復、テストなど)は、ここで合理的に回答できます。
Gilles「SO-邪悪なことをやめなさい」14年

1
Emacs 22はもはや「最近」ではありません。Emacs 23でさえも時代遅れです。
lunaryorn 2014年

1
それは野生で一般的であるため、私はemacs 22を含めました。たとえば、OSX 10.9にバンドルされています。
Paul Miller

Macの真面目なEmacsユーザーは、最近のバージョンをダウンロードします。Emacs 22はOS Xにのみ含まれています。これは、GPLv2でライセンスされた最後のバージョンであるためです(IMOでは完全に削除する必要があります)。23+の方がはるかに便利だと思います(IIRC Debian安定版はまだ23を使用しています)。
shosti 2014年

2
シーッシュ。質問を装った人は、 Emacsの22+について尋ね、あなたは、より新しいバージョンを主張するために「正しい」というリクエストにしたいですか?次に何が-誰かが尋ねた、forward-charそしてあなたはscroll-up代わりに尋ねられるように質問を変更したいですか?OPがEmacs 22+互換性を必要とする場合は、そのままにしておきます。そして、いいえ、提起された質問はOS Xだけに関するものではありません。そしてはい、古いEmacsバージョン(22歳以上のFWIWさえも)を使用している人はまだたくさんいます。
2014年

回答:


10

Elispはインタープリター型言語です。バージョン固有のコードをに配置できます.emacsが、正しいバージョンで動作していることをロード時にテストすることで保護できます。

(if (is-new-feature-available)
    (shiny-new-feature)
  (old-less-nifty-feature))

がtrueを返す場合に(shiny-new-feature)のみ評価されるため、このコードはすべてのバージョンで機能し(is-new-feature-available)ます。この回答の多くは、実装方法に当てられています(is-new-feature-available)

さまざまな機能セットへの対応

Emacsのバージョンをテストするよりも、機能が利用可能かどうかをテストすることをお勧めします。この機能はオプションパッケージとして利用できる場合があります。XEmacsまたは他のEmacsバリアントでコードを実行する場合、異なるバージョンで同じ機能を取得している可能性があります。関数boundpを使用して、変数が使用可能fboundpかどうかをテストし、関数が使用可能かどうかをテストします。

たとえば、次のスニペットはキーをバインドして、visual-line-mode利用可能な場合とlonglines-modeそうでない場合に切り替えます。

(global-set-key "\eml" (if (fboundp 'visual-line-mode)
                           'visual-line-mode
                         'longlines-mode))

場合によっては、機能をテストするよりも、小さなコードを実行して、未定義の関数や無効な引数などによるエラー無視する方が簡単です。大量のコードに対してこれを行わないでください。これにより、コードが非常に複雑になります。デバッグが難しい。

たとえば、ツールバーを表示したくありません。古いバージョンのEmacsにはまったくありませんでした。GNU EmacsとXEmacsはさまざまな方法でその機能を追加し、それをデフォルトにしました。以下に、それらをオフにする方法を示します。このset-specifier関数はXEmacsにdefault-toolbar-visible-p固有であり、十分に新しいバージョンのEmacsに固有です。を使用condition-caseすると、両方の要件が処理されます。GNU Emacsは専用の関数を提供するので、その関数が利用可能かどうかをテストするだけです。

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

一部の顔の名前はバージョンによって異なります。facep顔の名前の可用性をテストするために使用します。

(let ((face (if (facep 'mode-line) 'mode-line 'modeline)))
  (set-face-background face …))

素敵なパッケージが存在する場合はそれをロードし、そのパッケージが利用できない場合は何もしないこともあるでしょう。requireそのためのオプションの引数があります。

(require 'tex-site nil t) ;; Load AUCTeX if available

この引数はGNU Emacs 20.4で導入されたもので、XEmacsでは使用できません。そのため、これより前に戻りたい場合は、ラップするcondition-caseか、load代わりに使用する必要があります(既にロードされているライブラリをチェックしません)。 。

バージョンの依存関係をユーザーレベルの機能に制限します。サポートするすべてのバージョンで利用できない新しいプログラミング機能を使用しないでください。古いバージョンには互換性のあるバージョンを提供する必要があり、単一のバージョンを維持する方が簡単です。

場合によっては、多くの場所で機能が必要になることがあります。その機能は、気になるすべての実装で利用できますが、方法は異なります。これは、XEmacsとGNU Emacsの両方をサポートする場合にほとんど当てはまります。それらには、お互いの機能をコピーするが、それらのインターフェースはコピーしないという苛立たしい傾向がありました。この場合、互換性関数を定義する方が、使用時にテストするよりも便利です。

たとえば、次のコードは、現在のフレームのウィンドウシステム、最新のGNUの方法、最新のXEmacsの方法、および同じインスタンスで端末フレームとGUIフレームを組み合わせることができなかった古いスタイルの方法を返す関数を定義しています。

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

環境の依存関係

プラットフォームに依存する必要のあるコードはそれほど多くありません。変数system-typeはオペレーティングシステムを示します。私は排他的にいくつかのハックをアクティブ化するために使用しms-dosます(はい、私のファイルはその古いです)とwindows-nt

実行可能な検索パス(PATH)にディレクトリを追加することもできますが、通常は、Emacsの外部.profile、Unixライクなシステムの場合、Windowsのコントロールパネルを使用するのが最適です。外部プログラムが利用可能かどうかをテストするには、を呼び出しますexecutable-find

GUIの種類に応じて異なる動作をする必要があるコードについては、window-typeまたはその後続(上記を参照)を確認してください。

初期化ファイル

互換性を最大限にするには、コードをに配置します~/.emacs。GNU Emacs ~/emacs.dはバージョン22で調べ始めました。XEmacs ~/.xemacsはバージョン21.4で調べ始めました。別のアプローチは、互換性コードを~/.emacs挿入して、メインファイルをロードすることによって終了することです。(setq load-home-init-file t)XEmacsの最近のバージョンがXEmacs .emacsのみの場所に移動するかどうかを尋ねるのを避けるためにどこかに置きます。

Emacsのバージョンが異なると、一部のマクロの展開が異なり、互換性がない場合があります。そのため、バージョン間でバイトコンパイルされたファイルを共有せず、各マシンでファイルをコンパイルしてください。

機能が非推奨になることもありますが、サポートしたい他のバージョンにはそれがすべてあるため、それを使用したい場合があります。バイトコンパイラの警告はbyte-obsolete-variableプロパティから発生します。

(cond
 ((not (boundp 'desktop-enable))
  (defvaralias 'desktop-enable 'desktop-save-mode))
 ((get 'desktop-enable 'byte-obsolete-variable)
  (put 'desktop-enable 'byte-obsolete-variable nil)))

¹ 比較的古いのXEmacsと比べて、話します。


6

(コミュニティwiki。追加してください!)

  • 新しいEmacsバージョンで追加された、使用したいfboundp関数がある場合は、それがで定義されているかどうかを確認し、定義されていない場合は互換性関数を定義します。

    他のElispコードが同じfboundpトリックを使用している可能性があるため、互換性関数に実際の関数と同じ名前を付けることは悪い考えと考えられます。したがって、互換機能には接頭辞を使用defaliasし、定義されている場合は同じ名前に使用します。例えば:

    (if (fboundp 'propertize)
        (defalias 'my-propertize 'propertize)
      (defun my-propertize (string &rest properties)
        "Return a copy of STRING with text properties added.
    
     [Note: this docstring has been copied from the Emacs 21 version]
    
    First argument is the string to copy.
    Remaining arguments form a sequence of PROPERTY VALUE pairs for text
    properties to add to the result."
        (let ((str (copy-sequence string)))
          (add-text-properties 0 (length str)
                               properties
                               str)
          str)))
    
  • 一部の構成が特定のOSにのみ適用される場合、いくつかの異なる可能性があります。あなたは確認することができsystem-type、変数、戻りgnu/linuxdarwinwindows-ntおよびいくつかの他の(ドキュメンテーション文字列を参照してください)。

    window-systemdocstringには「この変数をブール値として使用することは非推奨」と記載されていますが、display-graphic-p代わりに使用することをお勧めしますが、あなたはを使いたくなるかもしれません。Emacsは現在、異なるフレームに異なるタイプのディスプレイを使用できることに注意してください(たとえば、端末の1つのフレームと「適切な」ウィンドウの別のフレーム)。これは驚きを引き起こす可能性があります。current-frame-configurationまたはget-buffer-window-listelispで使用して、正しい選択を行ってください。

  • emacsの適切なフレーバーで実行しているかどうかを確認する必要があります。featurepを使用してバリアントを確認します。例えば:

    (when (featurep 'xemacs)
       (require 'fsf-compat))
    

    これを使用して、特定のモジュールがロードされていることを確認することもできます。たとえば、common-lispのdefunを小さく簡単に定義するだけを使用する場合は、必須ではなく定義することを選択できます。例えば:

    (unless (featurep 'cl)
       (defun caaar (x)
          "Return the `car' of the `car' of the `car' of X."
          (car (car (car x)))))
    
  • .elcファイルの保存は避けてください。これらは、一部のEmacsバージョン間での上位または下位互換性がありません。


0

の関数cl-libを使用しているが、非推奨の非名前空間バージョンを使用したくない場合は、cl-lib互換ライブラリをプロジェクトの依存関係にします。これにより、名前空間cl-付きの関数を使用できるようになりますが、下位互換性は維持されます。


load-library:ロードファイルを開けません:cl-lib — cl-libとにかくなぜ私は欲しいのですか?cl少なくとも20年前から存在していたを超える利点は何ですか?
Gilles「SO-悪をやめる」

1
clは非推奨であり、おそらく最終的には削除される予定です。コードでそれを使用すると、かなり長い間バイトコンパイラの警告が発生します。その理由は、いくつかのcl名前(などdolist)を異なるセマンティクスで再利用したいためです。
shosti 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.