Index: Doc/lib/libreadline.tex =================================================================== --- Doc/lib/libreadline.tex (Revision 56089) +++ Doc/lib/libreadline.tex (Arbeitskopie) @@ -146,6 +146,49 @@ \end{seealso} +\subsection{Alternate Callback Interface + \label{alternate-callback-interface}} + +An alternate interface is available to using readline through the +blocking prompting \function{raw_input()} and \function{input()}. +Some applications need to interleave keyboard I/O with file, +device, or window system I/O, typically by using a main loop +to \function{select()} on various file descriptors. +To accomodate this need, readline can also be invoked as a ``callback'' +function from an event loop. +The following functions are available to make this easy. + +\begin{funcdesc}{callback_handler_install}{prompt, handler} +Set up the terminal for readline I/O and display the initial expanded +value of prompt. Save the value of handler to use as a function to +call when a complete line of input has been entered. +The function takes the text of the line as an argument. \versionadded{2.6} +\end{funcdesc} + +\begin{funcdesc}{callback_read_char}{} +Whenever an application determines that keyboard input is available, +it should call \function{callback_read_char()}, which will read the next +character from the current input source. If that character completes +the line, \function{callback_read_char()} will invoke the handler function +saved by \function{callback_handler_install} to process the line. +Before calling the handler function, the terminal settings are reset +to the values they had before calling \function{callback_handler_install}. +If the handler function returns, the terminal settings are modified +for readline's use again. +EOF is indicated by calling handler with a \code{None} line. +\versionadded{2.6} +\end{funcdesc} + +\begin{funcdesc}{callback_handler_remove}{} +Restore the terminal to its initial state and remove the line handler. +This may be called from within a callback as well as independently. +If the handler installed by \function{callback_handler_install} does not +exit the program, this function should be called before the program +exits to reset the terminal settings. +\versionadded{2.6} +\end{funcdesc} + + \subsection{Example \label{readline-example}} The following example demonstrates how to use the Index: Modules/readline.c =================================================================== --- Modules/readline.c (Revision 56089) +++ Modules/readline.c (Arbeitskopie) @@ -534,6 +534,124 @@ contents of the line buffer."); +#if defined(HAVE_RL_CALLBACK) + +/* GNU readline callback API */ + +static PyObject *callback_handler_hook = NULL; + +static void +rl_pycallback_handler(char *text) +{ + if (callback_handler_hook != NULL) { + PyObject *r; +#ifdef WITH_THREAD + PyGILState_STATE gilstate = PyGILState_Ensure(); +#endif + r = PyObject_CallFunction(callback_handler_hook, "s", text); + if (r == NULL) { + PyErr_Clear(); + Py_XDECREF(r); + } + else { + Py_DECREF(r); + } +#ifdef WITH_THREAD + PyGILState_Release(gilstate); +#endif + } +} + + +static PyObject * +callback_handler_install(PyObject *self, PyObject *args) +{ + /* get the prompt and the python callback function */ + char *prompt; + PyObject *handler = Py_None; + if (!PyArg_ParseTuple(args, "sO:callback_handler_install", + &prompt, &handler)) { + return NULL; + } + if (PyCallable_Check(handler)) { + PyObject *tmp = callback_handler_hook; + Py_INCREF(handler); + callback_handler_hook = handler; + Py_XDECREF(tmp); + } + else { + PyErr_SetString(PyExc_TypeError, + "callback_handler_install: handler not callable"); + return NULL; + } + rl_callback_handler_install(prompt, rl_pycallback_handler); + Py_INCREF(Py_None); + return Py_None; +} + +PyDoc_STRVAR(doc_callback_handler_install, +"callback_handler_install(prompt, handler) -> None\n\ +Set up the terminal for readline I/O and display the initial expanded\n\ +value of prompt. Save the value of handler to use as a function to\n\ +call when a complete line of input has been entered.\n\ +The function takes the text of the line as an argument."); + +/* rl_callback_read_char calls abort() if called when there is no + installed handler. SIGABRT catching seems overkill, + so we check if there was a call to handler_install before. + But: this means that Python may abort if there was an + intermediate call to handler_remove: e.g. raw_input or + simply by using the interactive interpreter. +*/ + +static PyObject * +callback_read_char(PyObject *self, PyObject *noarg) +{ + if (callback_handler_hook == NULL) { + PyErr_SetString(PyExc_TypeError, + "callback_read_char: no handler installed"); + return NULL; + } + rl_callback_read_char(); + Py_INCREF(Py_None); + return Py_None; +} + +PyDoc_STRVAR(doc_callback_read_char, +"callback_read_char() -> None\n\ +Whenever an application determines that keyboard input is available,\n\ +it should call callback_read_char(), which will read the next\n\ +character from the current input source. If that character completes\n\ +the line, callback_read_char will invoke the handler function\n\ +saved by callback_handler_install to process the line.\n\ +Before calling the handler function, the terminal settings are reset\n\ +to the values they had before calling callback_handler_install.\n\ +If the handler function returns, the terminal settings are modified\n\ +for readline's use again.\n\ +EOF is indicated by calling handler with a None line."); + +static PyObject * +callback_handler_remove(PyObject *self, PyObject *noarg) +{ + rl_callback_handler_remove(); + Py_XDECREF(callback_handler_hook); + callback_handler_hook = NULL; + Py_INCREF(Py_None); + return Py_None; +} + +PyDoc_STRVAR(doc_callback_handler_remove, +"callback_handler_remove() -> None\n\ +Restore the terminal to its initial state and remove the line handler.\n\ +This may be called from within a callback as well as independently.\n\ +If the handler installed by callback_handler_install does not exit\n\ +the program, this function should be called before the program\n\ +exits to reset the terminal settings.\n\ +(or the function referred to by the value of rl_deprep_term_function)"); + +#endif + + /* Table of functions exported by the module */ static struct PyMethodDef readline_methods[] = @@ -577,6 +695,14 @@ #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER {"clear_history", py_clear_history, METH_NOARGS, doc_clear_history}, #endif +#if defined(HAVE_RL_CALLBACK) + {"callback_handler_install", callback_handler_install, + METH_VARARGS, doc_callback_handler_install}, + {"callback_read_char", callback_read_char, + METH_NOARGS, doc_callback_read_char}, + {"callback_handler_remove", callback_handler_remove, + METH_NOARGS, doc_callback_handler_remove}, +#endif {0, 0} };