Apakah ada cara untuk menentukan wajah pada frame x / y (posisi mouse)?

8

Saat mencoba tema mode tertentu, tidak mungkin untuk menempatkan titik pada item bertema (misalnya yang harus dilakukan C-u C-x =) dan mengidentifikasi wajah yang digunakan.

Pikiran saya adalah menggunakan mouse untuk mengidentifikasi wajah yang digunakan, tetapi yang bisa saya dapatkan adalah frame x, posisi y (menggunakan (mouse-position))

Dari sana saya tidak tahu bagaimana mendapatkan definisi wajah di coords tersebut.

Bantuan apa pun dihargai.

ocodo
sumber

Jawaban:

4

Ini satu cara. Anda harus mengikat perintah ke acara mouse. Tetapi jika Anda menggunakan klik tombol-mouse maka Anda mungkin perlu untuk mengikat acara untuk bagian lain dari klik (misalnya ke bawah) ignore. Ini hanyalah sebuah contoh - Anda mungkin tidak ingin menyia-nyiakan C-mouse1perintah seperti itu.

Fungsi utama (perintah, sebenarnya) adalah describe-char. Ini menggambarkan titik pada posisi buffer yang diberikan. Bagian dari deskripsi itu termasuk properti teks dan overlay pada posisi itu, dan jika properti faceadalah salah satunya maka Anda akan melihat nilainya.

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

Ini mungkin sedikit lebih baik - hal di atas mungkin tidak berfungsi dalam beberapa konteks:

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

(Perhatikan juga yang C-x =terikat what-cursor-position, yang menggunakan describe-char. Jadi Anda berada di jalur yang benar dengan C-u C-x =.)


Yang menjadi perhatian Ido: Tidak seperti Icomplete, yang menggunakan overlay, mode Ido memasukkan teks dalam minibuffer. Tetapi alasan kode di atas tidak bekerja pada teks itu adalah karena mode Ido menghapus teks pada awal setiap perintah, menggunakan pre-command-hook. Jadi ketika perintah di atas dieksekusi, teks yang menunjukkan penyelesaian sudah dihapus.

Kode berikut mengatasi masalah itu, hanya untuk mode Ido. Itu memasukkan kembali teks yang menunjukkan penyelesaian di awal, dan kemudian menghapus penyelesaian di akhir.

(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)))
Drew
sumber
Nice one @drew sangat dihargai
ocodo
Oh, sayangnya ketika ini digunakan dalam minibuffer dengan ido-vertikal (dan lainnya) pesan: describe-char: No character follows specified positiondikembalikan oleh url-char. Saya kira itu karena minibuffer dibersihkan di beberapa titik setelah acara. Saya berasumsi 'ignoreakan menghentikan ini, tetapi itu tidak terjadi. Ada ide?
ocodo
Tolong beri resep langkah-demi-langkah. (Ia bekerja untuk saya: M-x some-text, C-mouse-1pada teks di minibuffer.) Anda harus tentu saja klik mouse pada posisi yang memiliki teks. Jika Anda mengklik setelah akhir teks maka Anda mendapatkan kesalahan yang Anda sebutkan.
Drew
Gunakan ido-vertikal-mode atau ido-grid-mode dengan ido-mode, sekarang Ctrl + klik pada teks pilihan Ido di minibuffer. Kesalahan.
ocodo
Ketika Anda mengklik pada daftar penyelesaian untuk mode Ido atau Icomplete, Anda mengklik melewati teks dalam buffer (minibuffer). Anda mengklik overlay (hanya). Jika Anda mengklik overlay yang ada di atas teks buffer maka tidak ada masalah, tetapi jika Anda mengklik melewati ujung buffer (yang Anda lakukan), maka Anda mendapatkan pesan kesalahan.
Drew
2

Jika Anda tidak dapat meletakkan titik di tempat dan penggunaan yang benar C-u C-x =, itu mungkin disebabkan oleh fakta bahwa elemen yang relevan ditampilkan melalui overlay sebelum / sesudah-string, atau karena elemen itu menghilang / berubah ketika Anda mencoba untuk memasukkan titik di itu atau ketika Anda C-u C-x =.

Anda dapat mencoba menghindari masalah tersebut sebagai berikut:

  • gunakan posn-at-x-yyang akan mengembalikan deskripsi apa yang ada pada koordinat x / y itu. Misalnya jika itu adalah sepotong teks yang diambil dari string setelah / sebelum-string, string itu akan disebutkan di sana (serta posisi dalam string itu), sehingga Anda dapat mencari properti wajah yang diterapkan ke string pada posisi itu.
  • Anda dapat menjalankan kode "di latar belakang" daripada melalui perintah. Misalnya dengan run-with-timerAnda dapat menjalankan kode setiap detik, mencetak hasilnya ke beberapa jenis buffer debug pilihan Anda.
Stefan
sumber
1

Anda dapat menggunakan packate telentang untuk membuat representasi teks yang dapat dibaca manusia dari teks, dengan informasi wajah. Sebagai contoh:

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

Jalankan M-x faceup-vire-buffer RET, dan berikut ini ditampilkan:

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

Wajah kunci-font standar direpresentasikan menggunakan nama pendek, seperti kuntuk font-lock-keyword-face, sedangkan wajah non-standar disajikan menggunakan nama lengkapnya.

(Wajah adalah sistem uji regresi untuk menyoroti paket, misalnya kata kunci fonta, representasi teks disimpan sebagai file referensi.)

EDIT:

Untuk menjawab pertanyaan dalam komentar: "Jika saya mencoba men-debug wajah-wajah yang digunakan dalam tampilan minibuffer apakah ini masih akan memberi saya info?"

Ya, benar. Namun, Anda harus mengikat fungsi ke tombol karena menjalankannya menggunakan M-xtidak akan berfungsi ketika minibuffer sedang digunakan. Sebagai contoh:

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

Jika Anda dengan "minibuffer" benar-benar bermaksud area gema - bahwa itu, Anda ingin memeriksa pesan saat ini Anda akan perlu sedikit lebih banyak. Fungsi berikut akan melakukan ini:

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

Misalnya, berikut ini:

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

Akan menunjukkan kepada Anda:

My «w:Message»
Lindydancer
sumber
Jika saya mencoba men-debug wajah yang digunakan dalam tampilan minibuffer apakah ini masih akan memberi saya info?
ocodo
@EmacsFodder Ya, lihat jawaban saya yang diperbarui.
Lindydancer
Untuk lebih spesifik, yang mendorong saya untuk mengajukan pertanyaan adalah mendapatkan wajah-wajah dari ido-vertikal dan ido-grid. Keduanya membilas buffer sebelum acara mouse (tampaknya).
ocodo
Meskipun secara teknis jawaban langsung untuk pertanyaan itu adalah, Anda tidak bisa. Metode ini sedikit lebih mudah daripada menjelajahi emacslisp dari mode mana pun. Meskipun itu sederhana seperti: Cs defface Ms o
ocodo
1

Solusi alternatif mungkin menggunakan pemilih warna dan memberikan nilai warna untuk list-faces-for-colordidefinisikan di bawah (jika pemilih warna agak mati, gunakan argumen jarak):

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