フレームx / y(マウスの位置)で顔を決定する方法はありますか?


8

特定のモードのテーマを設定しようとする場合、テーマを設定したアイテムにポイントを配置して(例:行うC-u C-x =)、使用されている顔を特定することはできません。

私の考えは、使用された顔を識別するためにマウスを使用することですが、私が得ることができるのは、フレームのx、y位置(を使用(mouse-position))だけです

そこから、それらの座標で顔の定義を取得する方法がわかりません。

どんな助けでもありがたいです。

回答:


4

ここに1つの方法があります。コマンドをマウスイベントにバインドする必要があります。ただし、マウスボタンのクリックを使用する場合は、クリックの他の部分(ダウンなど)のイベントをにバインドする必要がありますignore。これは単なる例です- C-mouse1そのようなコマンドを無駄にしたくない場合があります。

主な機能(実際にはコマンド)はdescribe-charです。これは、指定されたバッファー位置のポイントを示します。説明の一部には、テキストプロパティとその位置のオーバーレイが含まれています。プロパティfaceがこれらの1つである場合は、その値が表示されます。

(defun foo (event)
  (interactive "e")
  (let* ((mouse-pos  (event-start event))
         (pos-pt     (posn-point mouse-pos)))
    (describe-char pos-pt)))

(global-set-key [(control down-mouse-1)] 'ignore)
(global-set-key [(control mouse-1)] 'foo)

これは少し良いかもしれません-上記はいくつかのコンテキストでは機能しないかもしれません:

(defun foo (event)
  (interactive "e")
  (let* ((mouse-pos  (event-start event))
         (mouse-buf  (window-buffer (posn-window mouse-pos)))
         (pos-pt     (posn-point mouse-pos)))
    (with-current-buffer mouse-buf (describe-char pos-pt))))

(これもを使用C-x =するwhat-cursor-positionにバインドされていることに注意してくださいdescribe-char。したがって、で正しい軌道に乗っていましたC-u C-x =。)


Idoに関する懸念事項:オーバーレイを使用するIcompleteとは異なり、Idoモードはテキストをミニバッファーに挿入します。ただし、上記のコードがそのテキストに対して機能しないのは、イドモードが各コマンドの先頭にあるを使用してテキストを削除するためですpre-command-hook。したがって、上記のコマンドを実行すると、補完を示すテキストはすでに削除されています。

次のコードは、イドモードの場合のみ、この問題を解決します。最初に補完を示すテキストを再挿入し、最後に補完を削除します。

(defun foo (event)
  (interactive "e")
  (when (and (boundp 'ido-mode)  ido-mode) (ido-exhibit))
  (let* ((mouse-pos  (event-start event))
         (mouse-buf  (window-buffer (posn-window mouse-pos)))
         (pos-pt     (posn-point mouse-pos)))
    (with-current-buffer mouse-buf (describe-char pos-pt)))
  (when (and (boundp 'ido-mode)  ido-mode) (ido-tidy)))

素敵な1つは大いに高く評価されました
ocodo 2015年

ああ、残念ながら、これがido-vertical(およびその他)のミニバッファーで使用されると、describe-char: No character follows specified positiondescribe-charによってメッセージが返されます。イベント後のある時点でミニバッファーがクリアされたことが原因だと思います。私は'ignoreこれで止めると思いましたが、それは起こりません。何か案は?
ocodo 2015年

段階的なレシピを教えてください。(それは私のために働きます:M-x some-textC-mouse-1ミニバッファーのそのテキスト上で。)もちろん、テキストがある位置でマウスをクリックしなければなりません。テキストの終わりの後にクリックすると、あなたが言及したエラーが発生します。
2015年

ido-vertical-modeまたはido-grid-modeとido-modeを使用します。ミニバッファーでIdo選択テキストをCtrlキーを押しながらクリックします。エラー。
ocodo 2015年

IdoまたはIcompleteモードの補完リストをクリックすると、バッファー(ミニバッファー)内のテキストを過ぎてクリックしていることになります。オーバーレイ(のみ)をクリックしています。バッファテキストの上にあるオーバーレイをクリックしても問題はありませんが、バッファの端(これが何をしているのか)を過ぎてクリックすると、エラーメッセージが表示されます。
2015年

2

ポイントを正しい場所に配置してを使用できない場合C-u C-x =、関連する要素がオーバーレイの前後の文字列を介して表示されているか、その要素がポイントを挿入しようとすると表示されなくなるか変更されることが原因である可能性がありますそれまたはあなたC-u C-x =

次のようにして、これらの問題を回避することができます。

  • posn-at-x-yそのx / y座標にあるものの説明を返すuse を使用します。たとえば、後/前の文字列から取得されたテキストの一部である場合、その文字列はそこに(その文字列内の位置とともに)言及されるため、その位置でその文字列に適用されているfaceプロパティを参照できます。
  • コマンドではなく「バックグラウンドで」コードを実行できます。たとえばrun-with-timer、コードを毎秒実行して、選択したデバッグバッファに結果を出力できます。

1

packate faceupを使用すると、人間が読める形式のテキストを、顔情報とともに作成できます。例えば:

(defun foo (arg)
  (if arg 1 2))

を実行M-x faceup-vire-buffer RETすると、次のように表示されます。

(«k:defun» «f:foo» («v:arg»)
  («k:if» arg 1 2))

標準のフォントロック面はkforのように短い名前を使用して表されますが、font-lock-keyword-face非標準の面はフルネームを使用して表示されます。

(Faceupは、フォントロックキーワードなどのパッケージを強調表示するための回帰テストシステムです。テキスト表現は参照ファイルとして保存されます。)

編集:

コメントの質問に答えるには、「ミニバッファディスプレイで使用されている面をデバッグしようとしている場合でも、これで情報が得られますか?」

はい、そうです。ただし、M-xミニバッファーが使用されている場合は、関数をキーにバインドする必要があります。例えば:

(global-set-key (kbd "<f6>") 'faceup-view-buffer)

「ミニバッファ」が本当にエコー領域を意味する場合、それは現在のメッセージを調べたいので、もう少し必要になります。次の関数はこれを行います:

(defun my-faceup-view-current-message ()
  (interactive)
  (let ((msg (current-message)))
    (unless msg
      (error "Echo area is empty"))
    (with-temp-buffer
      (insert msg)
      (faceup-view-buffer))))

たとえば、次のとおりです。

(let ((s "My Message"))
  (add-text-properties 3 (length s) '(face font-lock-warning-face) s)
  (message s)
  (my-faceup-view-current-message))

表示されます:

My «w:Message»

ミニバッファディスプレイで使用されている面をデバッグしようとしている場合、これでも情報が得られますか?
ocodo 2015年

@EmacsFodderはい、私の最新の回答を参照してください。
Lindydancer、2015年

具体的に言うと、質問をするきっかけとなったのは、ido-verticalとido-gridから顔を出すことでした。どちらも、マウスイベントの前にバッファをフラッシュします(そのようです)。
ocodo 2015年

技術的には質問への直接的な回答はありますが、できません。この方法は、どちらのモードのemacslispを精査するよりも少し簡単です。それは次のように単純ですが、Cs defface Ms o
ocodo '

1

別の解決策は、カラーピッカーを使用して、list-faces-for-color以下で定義するカラー値を提供することです(カラーピッカーが少しずれている場合は、distance引数を使用します)。

(defun list-faces-for-color (color &optional distance)
  "List faces which use COLOR as fg or bg color.

            Accept colors within DISTANCE which defaults to 0."
  (interactive (list (read-color "Color: ")
                     (and current-prefix-arg
                          (prefix-numeric-value current-prefix-arg))))
  (with-help-window (get-buffer-create (format " *%s*" this-command))
    (dolist (face (sort
                   (list-faces--for-color color distance)
                   (lambda (f1 f2)
                     (string< (symbol-name f1)
                              (symbol-name f2)))))
      (list-faces--print-face face)
      (terpri))))

(defun list-faces--print-face (face)
  "Print face and its parents if any."
  (with-current-buffer standard-output
    (let ((fchain (cdr (list-faces--inheritance-chain face :foreground)))
          (bchain (cdr (list-faces--inheritance-chain face :background))))
      (insert (propertize (format "%s" face) 'face face))
      (cond (fchain
             (dolist (face fchain)
               (insert " > " (propertize (format "%s" face) 'face face))))
            (bchain
             (dolist (face bchain)
               (insert " > " (propertize (format "%s" face) 'face face))))))))

(defun list-faces--inheritance-chain (face attr)
  "Return inheritence change for face and attr."
  (let ((g (face-attribute face attr)))
    (if (and (stringp g)
             (not (string= "unspecified" g)))
        (list face)
      (let ((inherit (face-attribute face :inherit)))
        (when inherit
          (if (facep inherit)
              (cons face
                    (list-faces--inheritance-chain inherit attr))
            (if (consp inherit)
                (cl-dolist (face inherit)
                  (let ((res nil))
                    (when (and (facep face)
                               (setq res (list-faces--inheritance-chain face attr)))
                      (cl-return res)))))))))))


(defun list-faces--attribute (face attr)
  "Get face attribute of face as defined or inherited."
  (let* ((chain (list-faces--inheritance-chain face attr)))
    (cl-dolist (f (nreverse chain))
      (let ((g (face-attribute f attr)))
        (when (and (stringp g)
                   (not (string= "unspecified" g)))
          (cl-return g))))))



(defun list-faces--for-color (color &optional distance)
  "Return all faces with COLOR as fg or bg withing DISTANCE."
  (let ((faces ())
        (distance (or distance 0)))
    (mapatoms (lambda (atom)
                (when (facep atom)
                  (let ((fg (list-faces--attribute atom :foreground))
                        (bg (list-faces--attribute atom  :background)))
                    (when (or (and fg
                                   (<= (color-distance
                                        fg
                                        color)
                                       distance))
                              (and bg
                                   (<= (color-distance
                                        bg
                                        color)
                                       distance)))
                      (push atom faces))))))
    (delete-dups faces)))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.