2010-08-12 22 views
12

Versión corta: Al usar emacs 'xterm-mouse-mode, Somebody (emacs? Bash? Xterm?) Intercepta las secuencias de control de xterm y las reemplaza por \ 0. Esto es un problema en monitores anchos porque solo las primeras 223 columnas tienen mouse.Emacs, Unicode, secuencias de escape de ratón xterm y terminales anchos

¿Cuál es el culpable y cómo puedo evitarlo?

Por lo que puedo decir, esto tiene algo que ver con la compatibilidad con Unicode/UTF-8, porque no fue un problema hace 5-6 años cuando tuve un gran monitor por última vez.

Detalles de Gory siguen ...

¡Gracias!

Emacs xterm-mouse-mode tiene un manejo de debilidad muy conocido, clics del mouse comenzando alrededor de x = 95. A workaround, adoptado por versiones recientes de emacs, elimina el problema a x = 223.

Hace varios años descubrí que xterm codifica las posiciones en octetos de 7 bits. Dada la posición 'x' para codificar, con X = X-96, enviar:

\40+x (x < 96) 
\300+X/64 \200+X%64 (otherwise) 

hay que añadir uno a la posición x dada desde emacs, ya que las posiciones en xterm inicio a la una, no es cero. Por lo tanto, aparece el número mágico x = 95 porque está codificado como "\ 300 \ 200" - el primer número escapado. Alguien (emacs? Bash? Xterm?) Trata las secuencias de control como "C0" de ISO 2022. Comenzando en x = 159, cambiamos a secuencias "C1" (\ 301 \ 200), que también son parte de ISO 2022.

El problema coincide con las secuencias \ 302, que corresponde al límite x = 223 actual. Hace varios años pude extender el truco para interceptar manualmente las secuencias \ 302 y \ 303, lo que superó el problema. Avance rápido unos años, y hoy encuentro que estoy atrapado en x = 223 porque Alguien está reemplazando esas secuencias con \ 0.

Así, en el que cabría esperar al hacer clic en la línea 1, columna 250 para producir

ESC [ M SPC \303\207 ! ESC [ M # \303\207 ! 

informes En lugar de emacs (para cualquier col> 223)

ESC [ M SPC [email protected] ! ESC [ M # [email protected] ! 

Sospecho que Unicode/UTF -8 soporte es el culpable. Algunas excavaciones muestran que the Unicode standard allowed C0 and C1 sequences as part of UTF-8 until Nov 2000, y supongo que Alguien no recibió la nota (afortunadamente). Sin embargo, \ 302 \ 200 - \ 302 \ 237 son Unicode control sequences, por lo que Alguien los sorbe (¡haciendo quién sabe qué con ellos!) Y devuelve \ 0 en su lugar.

Algunas preguntas más detalladas:
- ¿Quién es esta Alguien que intercepta los códigos antes de que lleguen al búfer de pérdidas de emacs?
- Si realmente se trata de secuencias de control, ¿cómo es que los caracteres posteriores a \ 302 \ 237, que son codificaciones UTF-8 de Unicode imprimible, también vuelven a ser \ 0?
- ¿Qué hace que los emacs decidan si mostrar la pérdida como caracteres unicode o secuencias de escape octal, y por qué no coinciden los dos? Por ejemplo, mi cygwin emacs autogenerado 23.2.1 (xterm 229) informa \ 301 \ 202 para la columna 161, pero mis emacs provistos por rhel5.5 22.3.1 (xterm 215) informan "Â" (latín A con circunflejo) , que en realidad es \ 303 \ 202 en UTF-8!

Actualización:

Aquí es un parche contra xterm-261 que hace que emita posiciones del ratón en formato UTF-8:

diff -r button.c button.utf-8-fix.c 
--- a/button.c Sat Aug 14 08:23:00 2010 +0200 
+++ b/button.c Thu Aug 26 16:16:48 2010 +0200 
@@ -3994,1 +3994,27 @@ 
-#define MOUSE_LIMIT (255 - 32) 
+#define MOUSE_LIMIT (2047 - 32) 
+#define MOUSE_UTF_8_START (127 - 32) 
+ 
+static unsigned 
+EmitMousePosition(Char line[], unsigned count, int value) 
+{ 
+ /* Add pointer position to key sequence 
+  * 
+  * Encode large positions as two-byte UTF-8 
+  * 
+  * NOTE: historically, it was possible to emit 256, which became 
+  * zero by truncation to 8 bits. While this was arguably a bug, 
+  * it's also somewhat useful as a past-end marker so we keep it. 
+  */ 
+ if(value == MOUSE_LIMIT) { 
+  line[count++] = CharOf(0); 
+ } 
+ else if(value < MOUSE_UTF_8_START) { 
+  line[count++] = CharOf(' ' + value + 1); 
+ } 
+ else { 
+  value += ' ' + 1; 
+  line[count++] = CharOf(0xC0 + (value >> 6)); 
+  line[count++] = CharOf(0x80 + (value & 0x3F)); 
+ } 
+ return count; 
+} 
@@ -4001,1 +4027,1 @@ 
- Char line[6]; 
+ Char line[9]; /* \e [ > M Pb Pxh Pxl Pyh Pyl */ 
@@ -4021,2 +4047,0 @@ 
- else if (row > MOUSE_LIMIT) 
-  row = MOUSE_LIMIT; 
@@ -4028,1 +4052,5 @@ 
- else if (col > MOUSE_LIMIT) 
+ 
+ /* Limit to representable mouse dimensions */ 
+ if (row > MOUSE_LIMIT) 
+  row = MOUSE_LIMIT; 
+ if (col > MOUSE_LIMIT) 
@@ -4090,2 +4118,2 @@ 
-  line[count++] = CharOf(' ' + col + 1); 
-  line[count++] = CharOf(' ' + row + 1); 
+  count = EmitMousePosition(line, count, col); 
+  count = EmitMousePosition(line, count, row); 

Esperamos que esto (o algo parecido) aparecerá en una versión futura de xterm ... el parche hace que xterm funcione de la caja con emacs-23 (que asume la entrada de utf-8) y corrige los problemas existentes con xt-mouse.el también. Para utilizarlo con emacs-22 requiere una redefinición de la función se utiliza para decodificar posiciones del ratón (la nueva definición funciona bien con emacs-23 también):

(defadvice xterm-mouse-event-read (around utf-8 compile activate) 
    (setq ad-return-value 
     (let ((c (read-char))) 
      (cond 
      ;; mouse clicks outside the encodable range produce 0 
      ((= c 0) #x800) 
      ;; must convert UTF-8 to unicode ourselves 
      ((and (>= C#xC2) (< emacs-major-version 23)) 
      (logior (lsh (logand C#x1F) 6) (logand (read-char) #x3F))) 
      ;; normal case 
      (c))))) 

distribuir el defun como parte de los .emacs sobre todo máquinas en las que inicie sesión, y parchee el xterm en cualquier máquina desde la que trabaje. Voila!

ADVERTENCIA: Las aplicaciones que usan los modos de mouse de xterm pero no tratan su entrada como utf-8 se confundirán con este parche porque las secuencias de escape del mouse son más largas. Sin embargo, esas aplicaciones rompen horriblemente con el xterm actual porque las posiciones del mouse con x> 95 se parecen a los códigos utf-8, pero no lo son. Crearía un nuevo modo de mouse para xterm, pero ciertas aplicaciones (¡gnu screen!) Filtran las secuencias de escape desconocidas. Emacs es la única aplicación de mouse de terminal que utilizo, por lo que considero el parche una ganancia neta, pero YMMV.

+2

No tengo un terminal tan amplio y no soy un usuario de Emacs, pero esta pregunta es muy complicada. Detallado y al punto, por un nuevo usuario. No creo que pueda ayudarlo con esto (le tomaría bastante tiempo reproducir y analizar su configuración), pero ¿ha intentado usar "script" (la herramienta) para almacenar los bytes exactos que su emulador de terminal envía a la ¿solicitud? (Ah, y probablemente esta pregunta sea un candidato en Power User ...) – scy

+1

Hmm. Script ve lo mismo. También escribí un programa C rápido para habilitar el modo de mouse y luego convertir su stdin en una secuencia de octetos. $ xterm -e echo-octets Incluso ejecutándolo directamente desde xterm (arriba), con todo lo que se me ocurre establecer en 7 bits, los clics del mouse están limitados a \ 377 o menos - eso suena sospechosamente como un 8 -bit codificación. Compilado? De todos modos, no es emacs ... y con suerte no bash si lo anterior es correcto. – Ryan

Respuesta

3

OK, lo descubrió. En realidad, hay dos problemas.

En primer lugar, algunas inmersiones en la fuente muestran que xterm recorta la región habilitada para el mouse de la ventana a 223x223 caracteres, y envía 0x0 para todas las demás posiciones.

En segundo lugar, emacs-23 es consciente de UTF-8 y se confunde con eventos de mouse que tienen x> 160 y y> 94; en esos casos, la codificación de xterm para xey parece un carácter UTF-8 de dos bytes (por ejemplo, 0xC2 0x80) y, como resultado, la secuencia del mouse parece un carácter corto.

Estoy trabajando en un parche para xterm para que los eventos del mouse emitan UTF-8 (lo que desconfundiría emacs-23 y permitiría terminales de hasta 2047x2047), pero aún no estoy seguro de cómo resultará.

2

Creo que el problema que provocó que su solución (y la solución anterior que se incluyó en uno de los lanzamientos de v22) deje de funcionar en 23.2 está dentro de Emacs. 23.1 puede manejar clics del mouse después de la columna 95 usando urxvt, gnu screen, putty o iTerm, pero 23.2 no. Configurar todo configurado en latin-1 no hace diferencia. 23.1 tiene el mismo código en xt-mouse.el. src/lread.c y src/character.h cambiado, sin embargo, y de un vistazo, creo que el error está allí en alguna parte. En cuanto a lo que sucede después de la columna 223, no tengo ni idea.

Para beneficio de cualquier otra persona que esté molesta por la regresión de xt-mouse en 23.2 aquí hay una versión modificada de xterm-mouse-event-read que funciona con clics del mouse hasta col 222 (crédito a Ryan por> 222 overflow manejo que mi arreglo original carecía). Esto probablemente no funcionará en 23.1 o antes.

(defun xterm-mouse-event-read() 
    (let ((c (read-char))) 
    (cond ((= c 0) #x100) 
     ; for positions past col 222 emacs just delivers 
     ; 0x0, best we can do is stay at eol 
     ((= 0 (logand c (- #x100))) c) 
     ((logand C#xff))))) 

... Editar: Aquí está la versión de Emacs 24 (cabeza bzr). Funciona de nuevo en el 23,2 al Paso 222, pero carece de la> 222 desbordamiento manejo Ryan sugirió EOL:

(defun xterm-mouse-event-read() 
    (let ((c (read-char))) 
    (if (> C#x3FFF80) 
     (+ 128 (- C#x3FFF80)) 
     c))) 
1

Mientras que xterm ahora funciona en modo utf-8 con un parche, este truco utf-8 se romperá de la peor manera posible en cualquier otra configuración regional, ya que los caracteres Unicode simplemente se descartarán a menos que sean representables.

rxvt-unicode tiene (en versiones posteriores a 9.09) un modo 1015 que envía respuestas de la forma "ESC [código; x; y M", usando números decimales. Esto tiene la ventaja de que no necesita ninguna prueba de las aplicaciones y que también funciona en entornos locales que no sean de utf-8.

+0

Gracias por la actualización. De hecho, me gusta la solución rxvt mucho mejor en principio (es lo que vt100 debería haber hecho originalmente), pero rompe demasiadas otras aplicaciones. Ante la opción de romper algunas aplicaciones o forzarlas a reescribir todas, opté por la menos invasiva. Dicho esto, resulta que tuve que reescribir el manejo del mouse en la pantalla de gnu de todos modos, así que ... – Ryan

5

xterm-262 agrega el parche en la parte superior, sin embargo, este parche está completamente roto por el diseño. Los desarrolladores de Rxvt-unicode se dieron cuenta y agregaron otra extensión mucho mejor para informar las coordenadas del mouse.

En este momento estoy trabajando para obtener un amplio soporte para esto. Rxvt-unicode y iTerm2 ya son compatibles con ambas extensiones. Creé parches para xterm (para admitir la extensión urxvt), y para gnome-terminal, konsole y putty para admitir ambas nuevas extensiones. En cuanto a las aplicaciones, he agregado soporte para la extensión urxvt a Midnight Commander.

Únase a mí en mi esfuerzo y trate de convencer a más desarrolladores de terminales y aplicaciones para implementar estas extensiones (al menos el urxvt, porque el otro no puede ser reconocido automáticamente por las aplicaciones).

Consulte http://www.midnight-commander.org/ticket/2662 para obtener detalles técnicos y otros indicadores.

Cuestiones relacionadas