Fontificar una región de un búfer con otro modo principal

12

Tengo un búfer que muestra documentación para los módulos Ansible. Este búfer tiene su propio modo principal que proporciona todas las cosas estándar. En particular, se tipifica el búfer para resaltar marcado en línea, opciones, secciones, etc. En general, es bastante similar a M-x man.

En la parte inferior de la documentación, generalmente hay algunos ejemplos de código en YAML. Me gustaría tipificar estos también. Podría agregar mis propias palabras clave de bloqueo de fuente para YAML, por supuesto, pero prefiero volver a usar la fuente del modo YAML.

¿Cómo puedo hacer eso? Específicamente, ¿cómo puedo usar un modo principal diferente para fontificar una región particular de un búfer?

Tenga en cuenta que el modo YAML no necesita estar activo en esta región. Todo el búfer es solo un búfer de visualización pasivo, y no está destinado a ser editado. Realmente solo necesito la fuente producida como si el Modo YAML estuviera activo en esa región.

Supongo que podría copiar la región del búfer en un búfer temporal, habilitar el modo YAML, fontificar el búfer y copiar todas las propiedades del texto. Funcionaría eso? Si es así, ¿cómo copio las propiedades de texto y cuáles son las propiedades relevantes para copiar? ¿O hay un mejor enfoque?

Lunaryorn
fuente
¿Cómo se implementa la fuente no-yaml? ¿Aplica propiedades de texto manualmente o utiliza el modo de bloqueo de fuente?
Malabarba
Los enlaces en esta publicación resumen al menos una buena parte de las opciones disponibles: wisdomandwonder.com/link/8610/…
grettke

Respuestas:

10

Recientemente me encontré con un problema similar, básicamente quería fontificar fragmentos de código en la documentación que obtuve de otra fuente. Seguí el enfoque mencionado hacia el final de su respuesta y funcionó bien para mí. La función que terminé con algo como lo siguiente

(defun my-fontify-yaml (text)
  (with-temp-buffer
    (erase-buffer)
    (insert text)
    (delay-mode-hooks (yaml-mode))
    (font-lock-default-function 'yaml-mode)
    (font-lock-default-fontify-region (point-min)
                                      (point-max)
                                      nil)
    (buffer-string)))

Como señaló @Malabarba en los comentarios, el enfoque simple anterior no funciona si el búfer de destino usa el modo de bloqueo de fuente. Sin embargo, podemos engañar al modo de bloqueo de fuente para que crea que la cadena ya está bloqueada al establecer la propiedad de texto font-lock-faceen face, (obtenemos la facepropiedad establecida, cuando usamos la función anterior) y establecemos la propiedad de texto fontifieden t. La siguiente función toma una cadena devuelta por la función anterior y realiza el procesamiento requerido para que la cadena se inserte fontified (esto se toma de la org-src-font-lock-fontify-blockfunción org-mode

(defun my-fontify-using-faces (text)
  (let ((pos 0))
    (while (setq next (next-single-property-change pos 'face text))
      (put-text-property pos next 'font-lock-face (get-text-property pos 'face text) text)
      (setq pos next))
    (add-text-properties 0  (length text) '(fontified t) text)
    text))

Ahora puedes usarlo de la siguiente manera

(insert (my-fontify-using-faces (my-fontify-yaml "application: test\nversion: 1")))
Iqbal Ansari
fuente
Esta es la misma solución que encontré sx.el, pero es importante tener en cuenta que solo funcionará si el búfer de destino no usa el modo de bloqueo de fuente.
Malabarba
¡Derecho! Me acabo de dar cuenta de que esto funcionó para mí porque lo usé en el búfer donde no se usaba el bloqueo de fuente (búfer de ayuda)
Iqbal Ansari
@Malabarba encontró una manera de hacer que esto funcione con buffers de destino con el modo de bloqueo de fuente habilitado
Iqbal Ansari
Muchas gracias, funciona perfectamente !
lunaryorn
¡Oh bien! Me alegro de poder ayudar :)
Iqbal Ansari
3

Library Narrow Indirect ( narrow-indirect) puede ayudar aquí: eche un vistazo al comentario del encabezado. Se basa en:

  1. estrechamiento, que limita la edición a una parte en un búfer, y
  2. búferes indirectos, que copian un búfer en otro para el que puede cambiar el modo principal.

Tenga en cuenta que el estrechamiento está desactivado de forma predeterminada porque se considera no apto para principiantes (el enlace predeterminado es C-x n n). Puede habilitarlo poniendo lo siguiente en su archivo init:

(put 'narrow-to-region 'disabled nil)

También puedes mirar mi hecho myfn-narrow-indirecta mano en mi conf .

freakhill
fuente
¿El estrechamiento en realidad afecta el bloqueo de fuente, es decir, lo mantiene alejado de fuera de la región estrecha? ¿El bloqueo de fuente realmente nunca elimina las restricciones de búfer?
lunaryorn
Y de todos modos, un paquete wiki no es una opción.
lunaryorn
Además, no necesita eliminar la disabledpropiedad de un comando para llamarla desde Emacs Lisp. Solo afecta el uso interactivo.
lunaryorn
0

Sugeriría mirar org-src-font-lock-fontify-block que proporciona esta funcionalidad para los bloques fuente del modo org. Parece que solo copia las partes relevantes a otro búfer, habilita el modo principal allí y luego copia el texto con fuente. Hackish, pero parece funcionar.

Joakim Hårsman
fuente
2
Esta respuesta se parece más a un comentario en la medida en que proporciona una dirección sugerida para tratar el problema, pero no es una respuesta completa. Por favor considere cambiarlo a un comentario.
Dan