Existe-t-il un moyen de déterminer le visage à l'image x / y (position de la souris)?


8

Lorsque vous essayez de thématiser certains modes, il n'est pas possible de placer le point sur l'élément à thème (par exemple à faire C-u C-x =) et d'identifier le visage utilisé.

Ma pensée est d'utiliser la souris pour identifier le visage utilisé, mais tout ce que je peux obtenir est la position x, y du cadre (en utilisant (mouse-position))

De là, je ne sais pas comment obtenir la définition du visage dans ces coordonnées.

Toute aide est appréciée.

Réponses:


4

Voici une façon. Vous devez lier la commande à un événement de souris. Mais si vous utilisez un clic avec le bouton de la souris, vous devrez probablement lier l'événement à l'autre partie du clic (par exemple, vers le bas) ignore. Ce n'est qu'un exemple - vous ne voudrez peut-être pas gaspiller C-mouse1une telle commande.

La fonction principale (commande, en fait) est describe-char. Il décrit le point à une position tampon donnée. Une partie de cette description comprend les propriétés du texte et les superpositions à cette position, et si la propriété en facefait partie, vous verrez sa valeur.

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

Cela pourrait être légèrement meilleur - ce qui précède pourrait ne pas fonctionner dans certains contextes:

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

(Notez aussi que C-x =c'est lié à what-cursor-position, qui utilise describe-char. Donc vous étiez sur la bonne voie avec C-u C-x =.)


En ce qui concerne Ido: contrairement à Icomplete, qui utilise une superposition, le mode Ido insère du texte dans le mini-tampon. Mais la raison pour laquelle le code ci-dessus ne fonctionne pas sur ce texte est que le mode Ido supprime le texte au début de chaque commande, en utilisant pre-command-hook. Ainsi, lorsque la commande ci-dessus est exécutée, le texte indiquant les achèvements a déjà été supprimé.

Le code suivant résout ce problème, uniquement pour le mode Ido. Il réinsère le texte montrant les achèvements au début, puis supprime les achèvements à la fin.

(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 très apprécié
ocodo

Oh, malheureusement quand ceci est utilisé dans le mini-tampon avec ido-vertical (et autres) le message: describe-char: No character follows specified positionest retourné par describe-char. Je suppose que c'est dû au fait que le mini-tampon a été effacé à un moment donné après l'événement. J'ai supposé que 'ignorecela arrêterait cela, mais cela ne se produit pas. Des idées?
ocodo

Veuillez donner une recette étape par étape. (Il fonctionne pour moi: M-x some-text, C-mouse-1sur ce texte dans le mini - tampon.) Vous devez de cliquer cours de la souris à une position qui a le texte. Si vous cliquez après la fin du texte, vous obtenez l'erreur que vous avez mentionnée.
attiré

Utilisez le mode ido-vertical ou le mode ido-grid avec le mode ido, maintenant Ctrl + cliquez sur le texte de sélection Ido dans le mini-tampon. Erreur.
ocodo

Lorsque vous cliquez sur la liste des achèvements pour le mode Ido ou Icomplete, vous cliquez au-delà du texte dans le tampon (mini-tampon). Vous cliquez sur une superposition (uniquement). Si vous cliquez sur une superposition qui se trouve au-dessus du texte du tampon, il n'y a pas de problème, mais si vous cliquez au-delà de la fin du tampon (ce que vous faites), vous obtenez le message d'erreur.
Drew

2

Si vous ne pouvez pas placer le point au bon endroit et l'utiliser C-u C-x =, cela peut être dû au fait que l'élément pertinent est affiché via la chaîne avant / après d'une superposition, ou parce que cet élément disparaît / change lorsque vous essayez de placer le point dans ou quand vous C-u C-x =.

Vous pouvez essayer d'éviter ces problèmes comme suit:

  • utiliser posn-at-x-yqui renverra une description de ce qui est à cette coordonnée x / y. Par exemple, s'il s'agit d'un morceau de texte extrait d'une chaîne après / avant, cette chaîne sera mentionnée là-bas (ainsi que la position dans cette chaîne), vous pouvez donc rechercher la propriété face appliquée à cette chaîne à cette position.
  • vous pouvez exécuter le code "en arrière-plan" plutôt que via une commande. Par exemple, run-with-timervous pouvez exécuter le code toutes les secondes, en imprimant le résultat dans une sorte de tampon de débogage de votre choix.

1

Vous pouvez utiliser le pack up face vers le haut pour créer une représentation textuelle lisible par l'homme d'un texte, avec des informations sur le visage. Par exemple:

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

Exécutez M-x faceup-vire-buffer RET, et ce qui suit est affiché:

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

Les faces standard de verrouillage de police sont représentées en utilisant des noms courts, comme kpour font-lock-keyword-face, tandis que les faces non standard sont présentées en utilisant leur nom complet.

(Faceup est un système de test de régression pour mettre en évidence des packages, par exemple des mots-clés de verrouillage de police, la représentation textuelle est stockée en tant que fichier de référence.)

ÉDITER:

Pour répondre à la question dans le commentaire: "Si j'essaie de déboguer les visages utilisés dans un affichage à mini-tampons, est-ce que cela va me donner des informations?"

Oui. Cependant, vous devez lier la fonction à une clé car son exécution à l'aide de M-xne fonctionnera pas lorsque le mini-tampon est en cours d'utilisation. Par exemple:

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

Si vous par le "mini-tampon" voulait vraiment dire la zone d'écho - c'est-à-dire, vous voudriez inspecter le message actuel dont vous aurez besoin un peu plus. La fonction suivante le fera:

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

Par exemple, les éléments suivants:

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

Vous montrera:

My «w:Message»

Si j'essaie de déboguer les visages utilisés dans un affichage de mini-tampon, est-ce que cela va toujours me donner les informations?
ocodo

@EmacsFodder Oui, voir ma réponse mise à jour.
Lindydancer

Pour être très précis, ce qui m'a poussé à poser la question était d'obtenir les visages de l'ido-vertical et de l'ido-grid. Ils vident tous les deux le tampon avant l'événement de la souris (il semble).
ocodo

Bien que techniquement la réponse directe à la question soit, vous ne pouvez pas. Cette méthode est un peu plus facile que de récurer l'emacslisp de n'importe quel mode. Bien que ce soit aussi simple que: Cs defface Ms o
ocodo

1

Une autre solution pourrait être d'utiliser un sélecteur de couleurs et de fournir la valeur de couleur list-faces-for-colordéfinie ci-dessous (dans le cas où le sélecteur de couleurs est un peu décalé, utilisez l'argument 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)))
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.