¿Formas de variar discretamente la representación del texto?

12

Estoy escribiendo una extensión emacs para usar con reconocimiento de voz, y estoy buscando ayuda con una característica en particular. Algunas palabras que el reconocedor de voz (Dragón) reconoce de manera sistemática de manera deficiente: no importa cuántas veces lo entrenes, simplemente apestará al reconocer ciertas palabras. Al mismo tiempo, generalmente cuando escribe sobre un tema o cuando codifica, usará muchas de las mismas palabras una y otra vez.

Así que he escrito un modo que usa superposiciones para cambiar cómo se representan las palabras en el búfer. Toma una letra aleatoria en la palabra, la subraya en un color aleatorio y coloca una marca diacrítica aleatoria (acento, diéresis, etc.) sobre ella. Aquí hay una captura de pantalla (probablemente necesitará hacer zoom para ver marcas / subrayados):

ingrese la descripción de la imagen aquí

Luego puede decir "pelo púrpura p" y buscará la palabra con un subrayado púrpura debajo de su 'a' con una marca diacrítica que se parece al cabello y escribirá esa palabra por usted. Entonces, en la captura de pantalla anterior que dice que eso haría que emacs escriba "regexp-quote" por usted.

La idea es que esto le permite referirse a cualquier palabra que ya haya usado que esté en pantalla usando un conjunto finito de palabras que el reconocedor es consistentemente bueno para reconocer.

Funciona bastante bien, excepto que ocasionalmente hay una colisión. Para hacerlo, puedo aprender a referirme constantemente a las palabras de la misma manera que estoy usando bytes del hash md5 de la palabra en lugar de (random)tener un algoritmo que asigne los cambios para evitar colisiones. Solo he encontrado 6 colores fácilmente distinguibles (es difícil cuando el subrayado tiene solo un carácter de ancho y un solo píxel de grosor) y 3 signos diacríticos fácilmente distinguibles (fáciles de distinguir entre sí y tampoco confusos con un subrayado en el anterior línea o superpuesta con el subrayado), visto en la parte superior de la fuente de arriba.

Necesito más formas de alterar el renderizado para reducir la frecuencia de colisión. Idealmente, una modificación de representación debería:

  • No ser discordante con el resto del texto. Esto me ha llevado a descartar, por ejemplo, la propiedad de video inverso.
  • No se puede confundir fácilmente con otros cambios. Los overlines se confunden fácilmente con subrayados en la línea anterior. Muchos de los signos diacríticos se ven similares a menos que el tamaño de la fuente sea prácticamente impráctico.
  • Esté espacialmente cerca de donde están los otros cambios. En este momento, una vez que mi ojo encuentra el personaje objetivo, toda la información está allí, el marcador, el subrayado y la letra.
  • Funciona bien con una fuente de ancho fijo (necesaria para la codificación) que representa correctamente los signos diacríticos (tuve que cambiar a DejaVu Sans Mono de Consolas para que las marcas se procesen correctamente)
  • Trabajar en letras del alfabeto latino. Hay marcas de combinación árabes, por ejemplo, pero no se combinan en caracteres del alfabeto latino.
  • No cambie el color de la letra, ya que eso ya se está utilizando para resaltar la sintaxis.
  • Realmente sea factible en emacs con emacs lisp;)

¿Quizás hay caracteres especiales Unicode que controlan el renderizado que podrían ser abusados ​​para abrir nuevas posibilidades? ¿O una forma de engrosar los subrayados para poder distinguir fácilmente más colores? ¿O alguna otra característica oscura de emacs que le permite representar marcas en la parte superior de los caracteres además de Unicode?

Joseph Garvin
fuente
No es una respuesta directa a su pregunta, sino quizás un par de ideas que utilizan superposiciones para dar nuevas apariencias de personajes. Una idea sería concatenar / emparedar dos superposiciones, forzándolas a encajar en el mismo espacio que un personaje normal; por ejemplo, el primer personaje es una línea delgada con color agregado (char-to-string ?\uFEFF)y el otro es un personaje objetivo que se reduce en tamaño para que ambos quepan. Otra idea sería utilizar un tachado vertical (disponible en algunas fuentes, pero no en todas) similar a lo que se usa en la biblioteca vline.el emacswiki.org/emacs/VlineMode
leyes
@lawlist: esa idea de línea Unicode es interesante, me dejaría hacer una 'línea lateral'. ¿Tienes alguna idea de cómo reducir el tamaño del siguiente personaje? Tal vez podría generar una imagen para usar con la propiedad de visualización, pero AFAICT no hay forma de que emacs represente el texto en una imagen, por lo que tendría que hacer las imágenes fuera de emacs.
Joseph Garvin el
Este comentario reemplaza al comentario anterior (que eliminé), y el código en el siguiente enlace también se ha actualizado: contiene tres ejemplos (uno de los cuales es idéntico a la respuesta que publiqué a continuación en el hilo actual): stackoverflow .com / preguntas / 23744237 /…
abogados

Respuestas:

4

Otra posibilidad sería mostrar números de línea y decir el número de línea antes de la palabra, o, dado que mirar para obtener el número de línea exacto sería molesto, podría hacer que el algoritmo busque dentro de + o - 5 o 10 líneas del número que decir.

O quizás declare una región o función en la que está trabajando y haga que todas las búsquedas solo busquen allí. Supongo que eso limitaría las colisiones.

También puede representar símbolos Unicode después o antes de una palabra en un color dado para ayudarlos a destacar. Y también enmarca o subraya la palabra en otro color. De esta manera, podría tener 6 colores de palabras * 6 colores de símbolos * N posibilidades de símbolos. Probablemente puedas encontrar 10 buenos símbolos y tener 360 combinaciones. Por ejemplo, podría decir "estrella amarilla azul" para referirse a la palabra gato aquí.

ingrese la descripción de la imagen aquí

Si la estrella es demasiado discordante, podría acoplar: cuadro y dos diferentes: subrayados.

Entonces, puede referirse al árbol de palabras aquí usando "azul amarillo rojo" que le daría 216 combinaciones para usar.

ingrese la descripción de la imagen aquí

Jordon Biondo
fuente
1
Esperé un tiempo para ver si alguien podría encontrar otros trucos, pero probablemente voy a usar el color de subrayado doble, ya que agregar símbolos puede provocar una sangría. Aceptado, gracias.
Joseph Garvin el
2

¿Has oído hablar de ace-jump-mode ?

No cumple con ninguno de los requisitos que especifique, pero parece que encaja perfectamente con lo que está tratando de lograr. Permitiría al usuario especificar cualquier palabra diciendo solo 2 o 3 palabras.

Puede definir el conjunto de caracteres que le ofrece, por lo que puede evitar las consonantes que son difíciles de distinguir. Entonces el uso podría simplemente decir "arreglar un nueve" y corregir la novena palabra que comienza con a.

Malabarba
fuente
Vea mi comentario en la publicación de tmalsburg sobre por qué el modo ace-jump-jump no funcionó.
Joseph Garvin
1

Interesante pregunta. Apuesto a que obtendrás algunas sugerencias interesantes.

Una sugerencia menor que se me ocurre es usar diferentes colores y estilos para subrayar. Ver el manual de Elisp, el nodo Face Attributessobre el atributo :underliney sus :colory :stylecomponentes.

También puede experimentar con atributos :boxy diferentes anchos de línea y estilos, pero eso puede ser demasiado discordante.

Dibujó
fuente
1

Contestaré proponiendo una forma alternativa de seleccionar la palabra objetivo. Resalta la mitad de las palabras (elegidas al azar). El usuario dice "sí" si la palabra objetivo está resaltada y "no" de lo contrario. Si el usuario dijo "sí", tome todas las palabras que fueron resaltadas y resalte al azar la mitad de ellas. Si el usuario dijo "no", resalte aleatoriamente la mitad de las palabras que no se resaltaron. Nuevamente, el usuario indica si la palabra objetivo se resalta diciendo "sí" o "no". Repita eso hasta que solo se resalte la palabra objetivo.

Algunos beneficios de este enfoque:

  • Esto funciona, no importa cuántas palabras tenga en la pantalla.
  • No necesita colores elegantes, fuentes o símbolos. Una pantalla monocromática es suficiente.
  • Carga cognitiva muy baja porque es fácil saber si una palabra está resaltada o no.

Inconveniente: debe decir "sí" y "no" con demasiada frecuencia. Sin embargo, esto se soluciona con la siguiente variación de la idea: no resalte las palabras, sino que use colores para ellas. Dices que tienes 6 colores fácilmente distinguibles. Esto significa que si tiene 100 palabras en la pantalla, seleccionar la palabra objetivo requiere nombrar 2.6 colores en promedio. Si hay 1000 palabras, debe nombrar 3.9 colores en promedio.

Tmalsburg
fuente
1
Lamentablemente, el número de palabras pronunciadas es una métrica engañosa. El problema con este estilo de solución es que contiene percepción / acción de ida y vuelta. Tengo que ver el color, luego reaccionar, luego ver, reaccionar, ver. Decir 3 palabras sin tener que detenerse para mirar entre ellas debe ser más rápido en la práctica que una solución donde lo hace, especialmente con Dragon con baja latencia. Si estos viajes de ida y vuelta no fueran un problema, simplemente usaría el modo as-jump-jump. Con los signos diacríticos puedo mirar la pantalla una vez y conocer toda la secuencia de lo que necesito decir sin tener que hacer una pausa para que Dragon reaccione después de cada palabra.
Joseph Garvin
1

El siguiente es un ejemplo que utiliza una superposición con una imagen xpm para versiones gráficas de Emacs que admiten el formato de imagen xpm. Tiene 11 píxeles de ancho; 20 píxeles de alto; y tiene un número especificado por el usuario de 4 colores posibles. Estoy en una Mac con Snow Leopard 10.6.8 y la fuente que prefiero cuando uso Emacs es -*-Courier-normal-normal-normal-*-18-*-*-*-m-0-iso10646-1la frame-char-width11 y la frame-char-height20. He agregado una delgada línea amarilla vertical a la izquierda de la letra mayúscula "A" como ejemplo de cómo dibujar imágenes personalizadas. La sustitución del carácter en el punto se puede hacer mediante programación usando (char-after (point))y tomando ese número, que en este caso es 65 para la letra mayúscula "A", y sustituyendo la variable apropiada, por ejemplo, (cond ((eq (char-after (point)) 65) cap-ltr-a-xpm) . . .y usando esa variable en el colocación de superposición, por ejemplo,(overlay-put (make-overlay (point) (1+ (point))) 'display cap-ltr-a-xpm). Esto funciona muy bien tanto para los búferes truncados como para el ajuste de palabras porque la displaypropiedad de superposición en un carácter en el medio de una palabra no hace que el ajuste de palabras piense que la primera parte de la palabra pertenece al final de la línea anterior . Por supuesto, llevará tiempo crear una biblioteca personalizada de imágenes favoritas xpm.

ImageMagick es capaz de producir una xpm semi-precisa de un carácter en particular basado en una familia y tamaño de fuente específicos, pero no fue tan preciso como esperaba: aquí hay un enlace a instrucciones para usar esa utilidad externa: https: / /stackoverflow.com/a/14168154/2112489 En pocas palabras, el usuario debe estar preparado para pasar el tiempo personalizando las imágenes xpm a su gusto.

(defun xpm-example ()
(interactive)
"Doc-string"
  (let* (
      (cap-ltr-a-xpm `(image :type xpm :mask nil :ascent center :data
        "/* XPM */
        static char * letters_xpm[] = {
        /* columns rows colors chars-per-pixel */
        /* columns = 1 pixel in width -- see also (frame-char-width) */
        /* rows = 1 pixel in height -- see also (frame-char-height) */
        \"11 20 4 1\",
        \". c #000000\",
        \"+ c #FF0000\",
        \"@ c #7F0000\",
        \"% c yellow\",
        \"%..........\",
        \"%....++....\",
        \"%....++....\",
        \"%..++..++..\",
        \"%..++..++..\",
        \"%++......++\",
        \"%++......++\",
        \"%++......++\",
        \"%++......++\",
        \"%++......++\",
        \"%++......++\",
        \"%++++++++++\",
        \"%++++++++++\",
        \"%++......++\",
        \"%++......++\",
        \"%++......++\",
        \"%++......++\",
        \"%++......++\",
        \"%++......++\",
        \"%..........\"};"))  )
    (overlay-put (make-overlay (point) (1+ (point))) 'display cap-ltr-a-xpm)))
lista de leyes
fuente
@wasamasa - gracias - eliminé la declaración errónea con respecto a los mapas de bits XBM.
ley