performance – ¿Cómo prevenir la ralentización cuando un proceso inferior genera largas filas?

Pregunta:

Yo uso Emacs con Geiser para hackear algún código de Scheme. Mientras juego en el REPL, a veces evalúo expresiones que dan como resultado una gran cantidad de resultados, a menudo todos en una línea.

Por ejemplo, acabo de jugar con SRFI-41 (secuencias) y creé una secuencia de caracteres a partir de un archivo grande; luego forcé la secuencia y Geiser arrojó todo el contenido del archivo como una secuencia de caracteres en mi búfer. Casi de inmediato, Emacs se detuvo a medida que se agregaban más y más caracteres a la línea de salida, y no importa cuánto tiempo mantuve presionando Cg o Cc Cc no pude hacer que Emacs (o Geiser) se detuviera.

Esto rompió toda mi sesión de Emacs, ya que Emacs ahora ignora completamente mi entrada, pensando que debe dar prioridad a la impresión de este flujo de caracteres masivo en una línea en un búfer REPL de Geiser que no responde.

¿Hay algo que pueda hacer para proteger mi sesión de Emacs de mi curiosidad destructiva? (¿Por qué Emacs se vuelve tan lento cuando muestra líneas muy largas de todos modos?) ¿Puedo establecer un límite para las líneas largas y decirle a Emacs que está bien simplemente no intentar mostrar líneas muy largas?

Respuesta:

Como ya se respondió en los comentarios, Emacs volverse muy lento en su re-visualización para largas filas es un problema bien conocido . Arreglarlo sería muy bueno, pero necesita mucha reflexión para llevarlo a cabo correctamente. Tengo una idea de cómo se podría lograr en base a la sección 6.3 de este documento (básicamente, almacene la información de la línea visual en el búfer actual y actualícela al insertar espacios en blanco, mostrar propiedades, cambios de ventana, etc., luego use esa información en volver a mostrar el código para evitar buscarlo todo el tiempo), pero no estoy lo suficientemente familiarizado con los componentes internos de C para llevarlo a cabo.

Sin embargo, existen soluciones alternativas. Los más obvios serían ajustar los parámetros relacionados con la visualización (como, habilitar el truncamiento de líneas visuales en la instancia gráfica de Emacs, usar un Emacs no gráfico para hacerlo automáticamente, deshabilitar las funciones de Bidi, etc.) y preprocesar el contenido del archivo que usted ' volver a leer. Uno menos obvio es el posprocesamiento automático de los archivos, ya sea truncando sus líneas o agregando propiedades de texto que hacen que las líneas parezcan más cortas de lo que realmente son. Para convertir esto en una respuesta más interesante, presentaré un truco bastante feo de la opción anterior que solo funcionará para los modos derivados de comint :

(defun my-comint-shorten-long-lines (text)
  (let* ((regexp "^\\(.\\{80\\}\\).*?$")
         (shortened-text (replace-regexp-in-string regexp "\\1" text)))
    (if (string= shortened-text text)
        text
      (propertize shortened-text 'help-echo text))))

(add-hook 'comint-preoutput-filter-functions 'my-comint-shorten-long-lines)

Esto define my-comint-shorten-long-lines , una función que toma una cadena que posiblemente consta de muchas líneas y usa el poder de las expresiones regulares para reemplazar cualquier línea con una longitud de 80 caracteres o más con una versión abreviada que muestra el texto original al pasar el cursor sobre él. Cuando se usa como gancho en comint-preoutput-filter-functions , filtrará toda la salida de comint antes de que se muestre.

Sin embargo, esta versión del truco tiene una debilidad bastante grave. En los modos que tienen una fontificación básica en marcha (como, Mx ielm ), felizmente cortará las líneas que son parte de una cadena y de esa manera fontificará todo hasta la próxima cita como cadena. Eso no es lo que queremos y se puede arreglar con un poco más de dominio de las expresiones regulares (pero presumiblemente se romperá dentro de un REPL para un lenguaje como Python). Ya que estamos en eso, resaltemos también la salida abreviada:

(defun my-comint-shorten-long-lines (text)
  (let* ((regexp "^\\(.\\{80\\}\\).*?\\(\"?\\)$")
         (shortened-text (replace-regexp-in-string regexp "\\1\\2" text)))
    (if (string= shortened-text text)
        text
      (propertize shortened-text 'font-lock-face 'shadow 'help-echo text))))

(add-hook 'comint-preoutput-filter-functions 'my-comint-shorten-long-lines)

Eso es un poco mejor, pero sigue siendo feo. Pasar el cursor sobre la salida de algo como find / in Mx shell no es atractivo (lo ideal sería mostrar solo la línea no abreviada, no toda la salida), la detección de cadenas es rudimentaria en el mejor de los casos y el truncamiento podría indicarse mejor con elipses en lugar de fontificar todo. Además de eso, ni siquiera se garantiza que el texto que ingresa no se convierta en lotes. Todo esto pide a gritos hacer el paso de procesamiento en un búfer temporal, pero se dejará para el lector como ejercicio (o el autor como una posible publicación de blog).

Leave a Comment

Your email address will not be published.

Scroll to Top

istanbul avukat

-

web tasarım