Emacsでは、主に「バッファの開始/終了」と「テキストは読み取り専用」に関連するメッセージがミニバッファに表示されないようにしたい場合があります。
これらのメッセージがミニバッファーに表示されないようにする方法はありますか?
また、これらを無効にしたくないかもしれない重要な理由がありますか?額面通りに、モードラインで行番号とバッファー書き込みステータスを簡単に確認できます。
Emacsでは、主に「バッファの開始/終了」と「テキストは読み取り専用」に関連するメッセージがミニバッファに表示されないようにしたい場合があります。
これらのメッセージがミニバッファーに表示されないようにする方法はありますか?
また、これらを無効にしたくないかもしれない重要な理由がありますか?額面通りに、モードラインで行番号とバッファー書き込みステータスを簡単に確認できます。
回答:
Emacs 25ではinhibit-message
、非nil値にバインドすることでミニバッファーメッセージを抑制することができます。
(let ((inhibit-message t))
(message "Listen to me, you!"))
message1
はmessage3
この変数を尊重するを呼び出すため、これは必要です。
(let ((inhibit-message t)) (message make-progress-reporter))
message
はメッセージ文字列を返すことに注意してください。したがって、コードを評価するときに、返された文字列が表示されている可能性があります。キーバインディングでこのコードを評価すると、メッセージは出力されません(メッセージバッファーを除く)。
Lispコードからこれを並べ替えることができます。なぜ「並べ替え」なのですか?MESSAGEはLisp関数の代わりにCで定義されたプリミティブであり、Emacs Lispリファレンスマニュアルに従って、 Cコードからのプリミティブへの呼び出しはアドバイスを無視します。
したがって、希望する機能を実際に適切に実装するには、MESSAGEプリミティブをLisp関数として再定義する必要があります。完了したら、文字列MESSAGEを取得してミニバッファーにエコーするコードを使用してアドバイスし、表示したくないメッセージのリストと比較してから、MESSAGEを呼び出したり呼び出したりしません結果に。理論的には、これは例えば(defvar *message-prim* (symbol-function 'message))
、それから(defun message (format &rest args) ... (funcall *message-prim* format args))
- で実現できますが、プリミティブな引数が与えられるとSYMBOL-FUNCTIONは実際には呼び出し不可能な何かを返すので、FUNCALLはVOID-FUNCTION状態を通知します。
しかし、それが機能したとしても、プリミティブを再定義すると、関数がLispコードから呼び出されたときにのみ再定義が使用されることが保証されるため、実際にはトリックを行いません。Cコードの呼び出しはまだ原始的な定義を使用するかもしれません。(CコードがEmacs Lispを呼び出すことが可能であり、そのような場合は再定義を見ることができます;もちろん、CコードがCコードを呼び出すこともでき、そのような場合は元の定義を見ることになります。)
適切なメッセージ抑制機能を提供するために、Cコードにパッチを適用し、Emacsを再コンパイルすることを漠然と考えています。私はその機能を本当に必要としませんが、特に私がCハッカーではないので、それは興味深い練習になるかもしれません。それまでの間、私がホイップしたものは、ファイルにドロップされ、initファイルの1つからインクルードされ、好みに合わせてカスタマイズされると、抑制用にリストした文字列に完全に一致するLispコードからのメッセージを抑制します。抑制が有効になっている限り、これらのメッセージはミニバッファーに表示されません。*Messages*
バッファからもそれらを抑制するかどうかのオプションがあります。
;; message-suppression.el
;; a quick hack by Aaron (me@aaron-miller.me), 2013-11-12
;; half a solution for http://superuser.com/questions/669701/emacs-disable-some-minibuffer-messages
;; NB this does nothing until you
;; M-x customize-group RET message-suppression RET
;; and adjust to taste
(defgroup message-suppression nil
"Customization options for selective message suppression."
:prefix "message-suppression")
(defcustom message-suppression-enabled nil
"Whether or not to suppress messages listed in
`message-suppress-these'."
:group 'message-suppression
:tag "Suppress some messages?"
:type '(choice (const :tag "No" nil)
(const :tag "Yes" t)))
(defcustom message-suppression-to-messages-buffer t
"Whether or not to insert messages suppressed from the
minibuffer into the *Messages* buffer."
:group 'message-suppression
:tag "Insert suppressed messages into *Messages* buffer?"
:type '(choice (const :tag "No" nil)
(const :tag "Yes" t)))
(defcustom message-suppression-these nil
"A list of messages which the `message-except-these' advice
should suppress from being echoed in the minibuffer. Messages
are matched by `member', i.e., only exact strings match.
NB! Per the Emacs manual, calls from C code to primitives (such
as `message') ignore advice entirely, which means some messages
cannot be suppressed by this mechanism. ('Advising
Functions' in the Emacs Lisp Reference Manual, q.v.)"
:group 'message-suppression
:tag "Messages to suppress"
:type '(repeat (string))
:link '(info-link "(elisp)Advising Functions"))
(defadvice message (around message-suppress-advice)
"Suppress messages listed in `message-suppress-these' from being
echoed in the minibuffer."
(let ((message-string nil)
(current-buffer nil))
(if (and message-suppression-enabled
(length (ad-get-args 0))
(stringp (car (ad-get-args 0)))
;; message-string doesn't get set until here because `format'
;; will complain if its first argument isn't a string
(setq message-string (apply 'format (ad-get-args 0)))
(member message-string
message-suppression-these))
;; we won't call `message', but we might echo to *Messages*
(and message-suppression-to-messages-buffer
(progn
(setq current-buffer (current-buffer))
(switch-to-buffer (get-buffer-create "*Messages*"))
(goto-char (point-max))
(insert (make-string 1 10))
(insert message-string)
(switch-to-buffer current-buffer)))
ad-do-it)))
(ad-activate 'message)
実際にLispコードから生成されたメッセージで動作するようにこれをテストしました。たとえば、空の文字列引数を与えるとDESCRIBE-FUNCTIONによってエコーされる「関数を指定しませんでした」という苦情です。残念ながら、「バッファの始まり」、「バッファの終わり」、「テキストは読み取り専用です」など、抑制したいというメッセージはすべてCコードから発信されているように見えるため、次のことができません。この方法でそれらを抑制します。
ソースパッチにたどり着いた場合、それは(おそらく)Emacs 24.3に反するものであり、使用方法についての情報でこの回答を更新します。
Emacs 25およびおそらくいくつかの以前のバージョンでは、これを行う最もクリーンな方法は次のとおりです。
最初に定義します:
(defun suppress-messages (old-fun &rest args)
(cl-flet ((silence (&rest args1) (ignore)))
(advice-add 'message :around #'silence)
(unwind-protect
(apply old-fun args)
(advice-remove 'message #'silence))))
次に、作成したすべてのメッセージを抑制したい場合some-function
:
(advice-add 'some-function :around #'suppress-messages)
たとえば、次のように記述することにより、関数ispell-kill-ispell
(in ispell.el.gz
)によって生成される「Ispell process killed」というメッセージを抑制します。
(advice-add 'ispell-kill-ispell :around #'suppress-messages)
メッセージを再度有効にする必要がある場合は、次を実行します。
(advice-remove 'some-function #'suppress-messages)
注意すべき点がいくつかあります。
1)によって生成さsome-function
れるすべてのメッセージは、関数が呼び出すlisp関数によって生成されるすべてのメッセージと同様に抑制されます。
2)Cコードによって生成されたメッセージは抑制されませんが、おそらくそれはすべて最高です。
3)ファイルの-*- lexical-binding: t -*-
最初の行に含まれていることを確認する必要があり.el
ます。
しかし、どの関数が呼び出されたかをどのように見つけるのですか message
かですか?他の誰かが提案したようにコードをgrepすることもできますが、Emacsに代わって作業をさせる方が簡単です。
定義する場合:
(defun who-called-me? (old-fun format &rest args)
(let ((trace nil) (n 1) (frame nil))
(while (setf frame (backtrace-frame n))
(setf n (1+ n)
trace (cons (cadr frame) trace)) )
(apply old-fun (concat "<<%S>>\n" format) (cons trace args))))
してから:
(advice-add 'message :around #'who-called-me?)
メッセージにバックトレースが追加されます。これから、メッセージが生成された場所を簡単に確認できます。
これを逆にすることができます:
(advice-remove 'message #'who-called-me?)
別の方法としては、message
機能をアドバイスし、メッセージを印刷するかどうかを確認するテストを行います。問題のメッセージが固定文字列の場合、これは簡単です。たとえば、「Ispell process killed」を抑制するには、次のように定義できます。
(defun suppress-ispell-message (old-fun format &rest args)
(if (string= format "Ispell process killed")
(ignore)
(apply old-fun format args)))
してから:
(advice-add 'message :around #'suppress-ispell-message)
メッセージが複雑な場合、このアプローチはすぐに非常に面倒になります。
特定のメッセージを選択的に禁止する方法を求めているようです。その答えは、それらの特定のメッセージを発行するコードを再定義またはアドバイスする必要があるということです。
たとえば一部のコードの期間中にすべてのメッセージを防ぐには、flet
またはcl-flet
を使用して、message
ローカルで関数を(関数)に再定義できますignore
。またはで使用される技術を使用するedt-electric-helpify
:の元の定義保存message
、fset
しignore
、再fset
(使用することをお勧めですが、元のDEFにそれをunwind-protect
あなたがそれを行う場合)。
grep
かA
のdiredで。Emacs Lispソースファイルでエラーメッセージテキストを検索します(利用可能な場合はEmacs Cファイルでも検索できます)。HTH。
これは、「バッファーの開始」と「バッファーの終了」を抑制するために機能し、emacs 25を必要としません。
; Suppress "Beginning of buffer" and "End of buffer" messages
(defadvice previous-line (around silencer activate)
(condition-case nil
ad-do-it
((beginning-of-buffer))))
(defadvice next-line (around silencer activate)
(condition-case nil
ad-do-it
((end-of-buffer))))
https://lists.gnu.org/archive/html/help-gnu-emacs/2015-12/msg00189.htmlから着想を得ていますが、互換性を高めるために「defadvice」を使用しています。