2009-03-27 11 views
21

El título es un poco más específico que mi objetivo real:Usando GNU Readline; ¿cómo puedo agregar ncurses en el mismo programa?

Tengo un programa de línea de comandos que utiliza GNU Readline, principalmente para el historial de comandos (es decir, la recuperación de los comandos anteriores utilizando la flecha hacia arriba) y algunos otros detalles. En este momento la salida del programa aparece intercalada con la entrada del usuario, que a veces está bien, pero la salida es asíncrona (se produce a través de una conexión de red en respuesta a los comandos de entrada), y eso a veces resulta molesto (por ejemplo, si las líneas se emiten cuando el usuario está escribiendo una nueva entrada).

Me gustaría agregar una característica a este programa: una "ventana" separada para la salida. Pensé en usar ncurses para esto. Pero desde el ncurses FAQ parece que las dos bibliotecas no son fáciles de usar juntas.

Podría considerar el uso de Editline o tecla en lugar de Readline, pero no tengo claro si alguno de ellos resolverá mi problema. También consideraría utilizar algo distinto de ncurses, incluida una biblioteca que proporciona ambos tipos de funcionalidad (ventanas en modo texto e historial de comandos), pero no sé qué podría ser mejor.

Ah, y el soporte para texto en color puede obtener puntos de bonificación. Sospecho que puedo hacer eso con Readline, así que tal vez sea una preocupación aparte, pero si una solución a mi problema también hace que sea fácil agregar un poco de color a la salida, tanto mejor.

Estoy usando Ubuntu Hardy (Linux 2.6).

+0

¿Ha encontrado una solución? –

+0

Me rendí (y me quedé con readline). –

Respuesta

6

He hecho algunas búsquedas, y parece que estás de suerte.

Para las alternativas de ncurses hay SLang, Newt y Turbo Vision. Slang es mucho más que solo manejo de pantalla y por lo tanto más complejo , pero tal vez se puede utilizar para su propósito ?. Newt utiliza la pantalla de manejo y es mucho más simple, pero demasiado simple y de modo de un único subproceso para su propósito, creo.

Turbo Vision es la biblioteca de gráficos en modo texto de Borland, utilizada por todas sus herramientas a finales de los años 80/principios de los 90. Borland lanzó el código fuente cuando el mercado para ese tipo de cosas disminuyó, y hay ahora un puerto para Linux (nota al margen, this project parece haber escrito su propia implementación de turbovisión). Ese puerto no está muerto (hubo algunas actualizaciones de cvs este año que compilaron bien (las versiones anteriores no), pero ninguno de los ejemplos de TV que encontré estaban actualizados e I solo obtuve algunos de ellos compilar antes de renunciar al resto. Esto es un poco vergonzoso, porque la televisión era un ambiente encantador para usar. La televisión es por cierto C++ (y supongo que estás usando C?).

Para una alternativa a readline, no es libkinput, que tal vez funciona junto con ncurses (se dice que puede utilizar terminfo ncurses'. Pero yo soy no está seguro de si eso significa que puede coexiste junto con el uso de ncurses)?

¿Quizás una opción sea ejecutar readline "externamente" a su programa ncurses usando rlwrap?

+0

argot resulta ser un lenguaje en sí mismo. También es licencia GPL2 solo para la última versión. Esperaba que fuera una biblioteca. – matiu

+0

Tenga en cuenta que Newt es una capa sobre SLang. Puede ser más fácil de usar, pero es exactamente otra opción. –

2

No estoy seguro qué versión probaste A partir de hoy (2012.09.14) Es muy simple, solo tenemos que enganchar nuestra función personalizada a los siguientes punteros de función.

 
rl_getch_function 
rl_redisplay_function 
rl_completion_display_matches_hook 

Hice algo razonable here.

+0

¿Alguna idea sobre cómo hacer que la historia también funcione? – nccc

+1

OK, me enteré. Uno tiene que mostrar 'rl_display_prompt', luego' rl_line_buffer' y establecer el desplazamiento del cursor a 'rl_point + strlen (rl_display_prompt)'. – nccc

5

Esto me hizo golpearse la cabeza durante unas horas, por lo que acaba de salvar a la gente buscar en Google un poco de dolor:

Si' re usando el controlador incorporado SIGWINCH de ncurses con KEY_RESIZE, tenga en cuenta que readline establece las variables de entorno LINES y COLUMNS de forma predeterminada. Estos anulan cualquier cálculo de tamaño dinámico (generalmente con ioctl()TIOCGWINSZ) que ncurses haría de otra manera, lo que significa que seguirá obteniendo el tamaño de terminal inicial incluso después de cambiar el tamaño del terminal.

Esto puede evitarse configurando rl_change_environment en 0 antes de inicializar readline.

Actualización:

Aquí hay alguna información adicional espigué de las fuentes de readline:

SIGWINCH código de manejo de readline (que se utiliza si rl_catch_sigwinch es 1) no actualización LINES y COLUMNS, que parece como si debería ser suficiente para ncurses. Sin embargo, al usar la interfaz de línea de lectura alternativa (que tiene más sentido cuando se combina readline con ncurses), los manejadores de señal (incluido el de SIGWINCH) solo se instalarán durante la duración de cada llamada rl_callback_read_char(), lo que significa cualquier cambio de tamaño de terminal entre dos llamadas a rl_callback_read_char() no será visto por readline.

+1

Considere [formatear] (http://stackoverflow.com/help/formatting) su respuesta. Los comandos/código son difíciles de leer. – ryanyuyu

+1

@dotctor ¡Gracias por formatearlo para mí! – Ulfalizer

9

Ahora he creado un sencillo programa de ejemplo en GitHub: https://github.com/ulfalizer/readline-and-ncurses.

Admite el tamaño de terminal eficiente y eficiente y caracteres multibyte/combinando/anchos. El código tiene comentarios útiles.

pantalla de abajo:

Screenshot of program combining ncurses and readline

+0

¡Fantástico! ¿Cuál es la licencia del código? Me gustaría integrarlo con material con licencia de MIT si es posible. ¡Gracias! – cxw

+0

¡Me alegro de que sea útil! Podría ponerlo bajo MIT si eso sería la menor molestia. Me hubiera ido con ISC de otra manera, y MIT se ve similar. También tengo una versión que se ejecuta en un loop select() (o epoll() en este caso) por cierto, para https://github.com/ulfalizer/botniklas. Se desvió y aún no lo ha empujado, pero podría hacer una sucursal si estuviera interesado. – Ulfalizer

+0

Esa versión instala un controlador SIGWINCH (aunque usa signalfd() en lugar de un controlador ordinario) y permite leer readline directamente desde stdin. Eso también soluciona el problema con la búsqueda y los caracteres multibyte. – Ulfalizer

Cuestiones relacionadas