regular-expressions – ¿Plegar expresiones regulares personalizadas en emacs?

Pregunta:

Considere un patrón / expresión regular que llamaré reg que coincide varias veces en un búfer emacs. Quiero que emacs reconozca todas las coincidencias para reg y reemplace (temporalmente, como plegar) cada coincidencia de texto coincidente con el resultado de una función elisp personalizada aplicada a esa coincidencia en particular, a la que llamo f (coincidencia) . Además, el texto reemplazado debe estar (personalizable) resaltado (otro color, etc.) y si mueve el cursor a una ocurrencia de f (coincidencia) , debe mostrar la coincidencia original siempre que el cursor esté dentro de la coincidencia (si lo mueve afuera, solo muestra f (coincidencia) nuevamente).

Para tener un ejemplo simple en mente, digamos reg \[\[\!.*?\!\]\] Y la función elisp f podría simplemente traducir todas las letras minúsculas en el texto coincidente a mayúsculas y viceversa. Entonces, por ejemplo, [[!HelloWorld1!]] Debería doblarse a [[!hELLOwORLD1!]]

En mi caso particular, quiero que reemplace de una manera más compleja los resultados de los cálculos matemáticos de Python con los resultados en un archivo de látex usando pythontex.

¿Hay algún paquete que pueda hacer esto? Si hay varios paquetes, ¿cuál sería el "estado del arte" para hacer algo como esto?

Respuesta:

Solución basada en superposición

La biblioteca preview.el de auctex muestra cómo se puede hacer algo así con superposiciones.

Solución basada en bloqueo de fuentes

Otro paquete de última generación es hi-lock.el . No admite la configuración y el filtrado de propiedades de texto de forma predeterminada.

Paintover es una copia reducida modificada de hi-lock.el. Sirve como estudio de concepto para resolver esta pregunta a través de font-lock .

Reducción:

  1. El paquete solo proporciona paintover-regexp que corresponde a highlight-regexp .
  2. Solo se ha adaptado la compatibilidad con el modo de bloqueo de fuente. Las superposiciones no se admiten correctamente.

Modificación:

paintover-regexp acepta en comparación con highlight-regexp dos argumentos adicionales:

  1. una expresión para un plist PROPERTIES con formato (PROP1 VAL1 PROP2 VAL2 ...) . Esa es la lista proporcionada para los elementos FACENAME en las entradas de font-lock-keywords como '(face FACE PROP1 VAL1 PROP2 VAL2 ...) .
    • Anote la cita. La lista no se evalúa.
    • nil es un argumento de PROPERTIES aceptable.
  2. una función de filtro FILTER , se llama como (FILTER '(face FACE PROP1 VAL1 PROP2 VAL2 ...)) El filtro puede modificar el argumento de la lista y devolver la lista modificada que se usa para el elemento FACENAME .

El prefijo ha cambiado de hi-lock a paintover .

Notas:

  1. Debe agregar las propiedades que usa en la lista FACENAME usted mismo a font-lock-extra-managed-props .

Prueba:

emacs-versión: GNU Emacs 26.2 (build 2, x86_64-pc-linux-gnu, GTK+ Version 3.22.30) of 2019-04-12

Solución a su ejemplo de prueba:

  • iniciar emacs -Q
  • Coloque paintover.el en algún lugar de su load-path y ejecute (require 'paintover.el)
  • Busque el archivo test.tex con el contenido a continuación.
  • Pegue el código Elisp a continuación en su búfer *scratch* y evalúe ese búfer con Mx eval-buffer .

Contenido de test.tex :

[[!HelloWorld1!]]

Second time: [[!This is the END!]] try again!

Let's try another time [[!Another Time!]].

Another case [[!SoMe String WiTH CaPITALS and lower case!]]

Pega en tu búfer *scratch* :

(defun invert-case (str)
  "Return new string with case-inverted characters from STR."
  (cl-map 'string
          (lambda (char)
            (let (case-fold-search)
              (cond
               ((string-match "[[:lower:]]" (string char))
                (upcase char))
               ((string-match "[[:upper:]]" (string char))
                (downcase char))
               (t char))))
          str))
;; Test: (invert-case "Hello You own mE $11")

(defun paintover-flush-once ()
  (message "paintover-flush-once")
  (remove-hook 'post-command-hook #'paintover-flush-once t)
  (font-lock-flush)
  (font-lock-ensure))

(with-current-buffer "test.tex"
  (let ((re "\\[\\[\\!\\(.*?\\)\\!\\]\\]"))
    (when (assoc-string re paintover-interactive-patterns)
      (paintover-unface-buffer re))
    (cl-pushnew 'display font-lock-extra-managed-props)
    (cl-pushnew 'cursor-sensor-function font-lock-extra-managed-props)
    (cursor-sensor-mode)
    (paintover-regexp
     re
     'paintover-yellow
     '(cursor-sensor-functions
       ((lambda (&rest _args) ;; sensor function
          (add-hook 'post-command-hook #'paintover-flush-once nil t))))
     (lambda (expr) ;; filter
       (append expr
               (and (null (paintover-in paintover-point (match-beginning 0) (match-end 0)))
                    (list 'display (format "[[!%s!]]" (invert-case (match-string 1))))))))))

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top

web tasarım