`find-file-noselect`の何が問題になっていますか?


11

lunaryornによる最近の回答で、彼は次のように述べています。

ただし、すでにコメントで述べられている理由から、私はOrgの他のほとんどの部分に対してお勧めします。それは古く、レガシーで有害な慣例(たとえば、非対話的にファイルを読み取るfind-file-noselect)でいっぱいです。

find-file-noselectElispプログラムでファイルを読み取るのが悪い考えである理由を誰かが説明できますか?もっと良い方法はありますか?私のプロジェクトの1つでそれを使用することを考えていたので、私は尋ねています。


good-practices以前はタグがなかったようです。それを使うのは良い考えですか?
mbork 2014年

good-practicesそれは、SEによって眉をひそめられている「メタタグ」のカテゴリーに該当すると思います。
nispio 2014年

1
@nispio有効なタグだと思いますが、もちろんこれをメタに適用できます。
Malabarba 2014年

1
@nsipio:その記事をざっと読みましたが、同意しません。しかし、決めるのは私ではありません。;-)
mbork 2014年

回答:


14

TL; DR:実際に何が起こるかを制御find-file-noselectでき、ユーザーがで何を有効にしたかに応じて、バッファで任意のマイナーモードが有効になる可能性がありますinit.el。また、クリーンアップは難しいです。

使用with-temp-bufferしてinsert-file-contents代わりに。バッファに特定のメジャーモードまたはマイナーモードが必要な場合は、それらを明示的に有効にします。ファイルを書き込むには、with-temp-file代わりにを使用します。その名前にかかわらず、任意のファイルに書き込むことができます。

副作用

find-file-noselect含む多くの副作用があります

  • インタラクティブに質問する(それだけで非インタラクティブに使用することはできません)、
  • 読み取り専用ファイルの表示モードを自動的に有効にする、
  • それ以外の場合は通常モードに入る
  • と実行していfind-file-hookます。

通常モード自体

  • 現在のバッファに適切なメジャーモードを自動的に選択し、
  • 対応するすべてのメジャーおよびマイナーモードフックを実行します。
  • そして、現在のバッファのすべてのローカル変数、つまりファイル変数とディレクトリ変数を読み取ります。これらも、安全でないローカル変数についてインタラクティブな質問をする場合があります。

すべてのフックが実行されるので、ユーザーがで有効にしたすべてのマイナーモードとフック関数を取得しますinit.el。これにより、軽微な不便さ(望ましくないマイナーモードが有効になっている場合)から大混乱(ユーザーが期待するフック関数を追加した場合)まで、すべての原因となる可能性があります。インタラクティブなコンテキストから呼び出されます)。

例については、https://github.com/flycheck/flycheck/issues/366を参照してください。を使用するとfind-file-noselect、Flycheckによってデータファイルの構文チェックが行われ、Emacsのシャットダウン時に発生したため、適切にクリーンアップして一時ファイルを残しておく時間はありませんでした。

掃除

ではfind-file-noselect、あなたは再びバッファを殺すために余分に注意する必要があります。 find-file-noselectあなたのためにそれをしません。

バッファーをどこかに覚えておく必要があり、unwind-protectローカルでない出口の場合でもバッファーが強制終了されるように注意深く使用する必要があります。

代替案

ファイルを読み取るには、とを使用with-temp-bufferします。insert-file-contentsこれは、コーディングシステムの変換などの最も基本的なことだけを行いますが、質問したり、フックを有効にしたり、ローカル変数を設定したりしません。

(with-temp-buffer
  (insert-file-contents (locate-user-emacs-file "foo.el"))
  ;; Enter the major mode explicitly
  (emacs-lisp-mode)
  ;; …
  )

with-temp-buffer 本体の最後にある一時バッファーを適切に強制終了するように注意します。

ファイルを書き込むにはwith-temp-file、を使用します。これにより、一時バッファーが作成され、本文の最後にある指定されたファイル名に内容が書き込まれます。

(with-temp-file  (locate-user-emacs-file "foo.el")
  (prin1 (list 'my 'data) (current-buffer)))

10

Elispマニュアルのセクション24.3から:

ファイルの内容をバッファにコピーするには、関数を使用します insert-file-contents。(insert-fileマークを設定するので、Lispプログラムでコマンドを使用しないでください。)

Elispのドキュメントを検索するとfind-file-noselect、ファイルをバッファに読み込むだけではないことがわかります。おそらく、この機能の使用が悪い考えである人々は、望ましくない可能性のある副作用について考えていますか?何を成し遂げたいかによりますね。可能な限りクリーンで手つかずのバッファコンテンツを使用する場合は、古くて信頼できるwith-temp-buffer+のinsert-file-contents組み合わせを使用することをお勧めします。バッファの内容をfind-file生成物と同じようにたい場合、おそらく使用たいfind-file-noselectですか?または多分彼は考えていたfind-file;)


3
何かが非対話的に行われている場合、「バッファの内容をfind-fileが生成するものに近づけたい」というシナリオは見られません。find-fileは、あらゆる種類のフックを含む大量の不要な処理を行うため、処理が遅くなります。あなたが望むかもしれないfind-fileの唯一の「機能」はmajor-modeですが、それからそれを自分でアクティブ化する必要があります(find-fileがとにかく望むモードをオンにすることさえ保証できません)。
Malabarba 2014年

Malabarba:バッファーをユーザーが編集できるようにしておくつもりなら、find-fileプロセスを真似した方がいいでしょう。
フィル、2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.