C'è un modo per determinare la faccia nel riquadro x / y (posizione del mouse)?


8

Quando si tenta di applicare un tema a determinate modalità, non è possibile posizionare il punto sull'elemento a tema (ad esempio, fare C-u C-x =) e identificare la faccia utilizzata.

Il mio pensiero è di usare il mouse per identificare la faccia usata, ma tutto quello che posso ottenere è la cornice x, y posizione (usando (mouse-position))

Da lì non so come ottenere la definizione del viso a quei coords.

Qualsiasi aiuto è apprezzato.

Risposte:


4

Ecco un modo. È necessario associare il comando a un evento del mouse. Ma se si utilizza un clic del pulsante del mouse, sarà probabilmente necessario associare l'evento per l'altra parte del clic (ad esempio verso il basso) ignore. Questo è solo un esempio: potresti non voler sprecare C-mouse1con un tale comando.

La funzione principale (comando, in realtà) è describe-char. Descrive il punto in una determinata posizione del buffer. Parte di quella descrizione include le proprietà del testo e le sovrapposizioni in quella posizione, e se la proprietà faceè una di queste, vedrai il suo valore.

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

Questo potrebbe essere leggermente migliore - quanto sopra potrebbe non funzionare in alcuni contesti:

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

(Nota anche che C-x =è vincolato a what-cursor-position, che utilizza describe-char. Quindi eri sulla strada giusta con C-u C-x =.)


Per quanto riguarda Ido: A differenza di Icomplete, che utilizza una sovrapposizione, la modalità Ido inserisce il testo nel minibuffer. Ma il motivo per cui il codice sopra non funziona su quel testo è che la modalità Ido rimuove il testo all'inizio di ogni comando, usando pre-command-hook. Quindi, quando viene eseguito il comando sopra, il testo che mostra i completamenti è già stato rimosso.

Il codice seguente risolve questo problema, solo per la modalità Ido. Reinserisce il testo che mostra i completamenti all'inizio, quindi rimuove i completamenti alla fine.

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

Nice one @drew molto apprezzato
ocodo

Oh, sfortunatamente quando questo è usato nel minibuffer con ido-verticale (e altri) il messaggio: describe-char: No character follows specified positionè restituito da descriviamo-char. Immagino sia dovuto al fatto che il minibuffer sia stato eliminato a un certo punto dopo l'evento. Ho pensato 'ignoreche ciò avrebbe impedito questo, ma ciò non sta accadendo. Qualche idea?
ocodo,

Si prega di dare una ricetta passo-passo. (Funziona per me: M-x some-text, C-mouse-1su quel testo nel minibuffer.) È necessario ovviamente clic con il mouse in una posizione che ha il testo. Se si fa clic dopo la fine del testo, viene visualizzato l'errore indicato.
Disegnò il

Usa la modalità ido-verticale o la modalità ido-griglia con la modalità ido, ora Ctrl + fai clic sul testo di selezione Ido nel minibuffer. Errore.
ocodo

Quando si fa clic sull'elenco dei completamenti per la modalità Ido o Icomplete, si fa clic oltre il testo nel buffer (minibuffer). Stai facendo clic su un overlay (solo). Se si fa clic su una sovrapposizione che si trova sopra il testo del buffer, non si verificano problemi, ma se si fa clic oltre la fine del buffer (che è ciò che si sta facendo), viene visualizzato il messaggio di errore.
Disegnò il

2

Se non riesci a mettere il punto nel punto e nell'uso corretti C-u C-x =, potrebbe essere dovuto al fatto che l'elemento rilevante viene visualizzato tramite una stringa pre / after di un overlay o perché tale elemento scompare / cambia quando si tenta di inserire un punto o quando tu C-u C-x =.

Puoi provare a evitare questi problemi come segue:

  • uso posn-at-x-yche restituirà una descrizione di ciò che è a quella coordinata x / y. Ad esempio, se si tratta di un pezzo di testo preso da una stringa after / before, quella stringa verrà menzionata lì (così come la posizione all'interno di quella stringa), quindi puoi cercare la proprietà della faccia applicata a quella stringa in quella posizione.
  • puoi eseguire il codice "in background" anziché tramite un comando. Ad esempio con run-with-timerte puoi eseguire il codice ogni secondo, stampando il risultato in una sorta di buffer di debug di tua scelta.

1

È possibile utilizzare il packate a faccia in su per creare una rappresentazione umana testo leggibile di un testo, con informazioni sul volto. Per esempio:

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

Esegui M-x faceup-vire-buffer RETe viene visualizzato quanto segue:

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

Le facce standard di blocco dei caratteri sono rappresentate usando nomi brevi, come kper font-lock-keyword-face, mentre le facce non standard sono presentate usando il loro nome completo.

(Faceup è un sistema di test di regressione per evidenziare i pacchetti, ad esempio parole chiave con blocco dei caratteri, la rappresentazione del testo viene memorizzata come file di riferimento.)

MODIFICARE:

Per rispondere alla domanda nel commento: "Se sto cercando di eseguire il debug dei volti utilizzati in un display di un minibuffer, questo mi darà ancora le informazioni?"

Sì, lo fa. Tuttavia, è necessario associare la funzione a un tasto poiché eseguirla utilizzando M-xnon funzionerà quando il minibuffer è in uso. Per esempio:

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

Se per "minibuffer" intendevi davvero l'area dell'eco, che ti piacerebbe ispezionare il messaggio corrente, avrai bisogno di qualcosa in più. La seguente funzione lo farà:

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

Ad esempio, quanto segue:

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

Ti mostrerà:

My «w:Message»

Se sto cercando di eseguire il debug dei volti utilizzati in un display di un minibuffer, questo mi darà ancora le informazioni?
ocodo,

@EmacsFodder Sì, vedi la mia risposta aggiornata.
Lindydancer,

Per essere molto specifici, ciò che mi ha spinto a porre la domanda è stato ottenere le facce da ido-verticale e ido-griglia. Entrambi svuotano il buffer prima dell'evento del mouse (sembra).
ocodo,

Mentre tecnicamente la risposta diretta alla domanda è, non puoi. Questo metodo è un po 'più semplice rispetto alla pulizia dell'emacslisp di qualunque modalità. Anche se questo è semplice come: Cs defface Ms o
ocodo

1

Una soluzione alternativa potrebbe essere quella di utilizzare un selettore di colori e fornire il valore del colore list-faces-for-colordefinito di seguito (nel caso in cui il selettore di colori sia un po 'spento, utilizzare l'argomento della distanza):

(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)))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.