(original) (raw)

Index: Doc/lib/libreadline.tex =================================================================== --- Doc/lib/libreadline.tex (revision 41788) +++ Doc/lib/libreadline.tex (working copy) @@ -112,11 +112,24 @@ possible completion starting with \var{text}. \end{funcdesc} +\begin{funcdesc}{set_completion_display_matches_hook}{\optional{function}} +Set or remove the completion display function. If \var{function} is specified, +it will be used as the new completion display function; if omitted or +\code{None}, any completion display function already installed is removed. The +completion display function is called as \code{\var{function}(\var{substitution}, +\var{[matches]}, \var{longest_match_length})} once each time matches +need to be displayed. +\end{funcdesc} + \begin{funcdesc}{get_completer}{} Get the completer function, or \code{None} if no completer function has been set. \versionadded{2.3} \end{funcdesc} +\begin{funcdesc}{get_completion_type}{} +Get the type of completion being attempted. +\end{funcdesc} + \begin{funcdesc}{get_begidx}{} Get the beginning index of the readline tab-completion scope. \end{funcdesc} Index: Modules/readline.c =================================================================== --- Modules/readline.c (revision 41788) +++ Modules/readline.c (working copy) @@ -190,6 +190,7 @@ /* Exported functions to specify hook functions in Python */ +static PyObject *completion_display_matches_hook = NULL; static PyObject *startup_hook = NULL; #ifdef HAVE_RL_PRE_INPUT_HOOK @@ -197,6 +198,20 @@ #endif static PyObject * +set_completion_display_matches_hook(PyObject *self, PyObject *args) +{ + return set_hook("completion_display_matches_hook", + &completion_display_matches_hook, args); +} + +PyDoc_STRVAR(doc_set_completion_display_matches_hook, +"set_completion_display_matches_hook([function]) -> None\n\ +Set or remove the completion display function.\n\ +The function is called as\n\ + function(substitution, [matches], longest_match_length)\n\ +once each time matches need to be displayed."); + +static PyObject * set_startup_hook(PyObject *self, PyObject *args) { return set_hook("startup_hook", &startup_hook, args); @@ -237,6 +252,18 @@ static PyObject *endidx = NULL; +/* Get the completion type for the scope of the tab-completion */ +static PyObject * +get_completion_type(PyObject *self, PyObject *noarg) +{ + return PyInt_FromLong(rl_completion_type); +} + +PyDoc_STRVAR(doc_get_completion_type, +"get_completion_type() -> int\n\ +Get the type of completion being attempted."); + + /* Get the beginning index for the scope of the tab-completion */ static PyObject * @@ -549,6 +576,8 @@ METH_NOARGS, get_history_length_doc}, {"set_completer", set_completer, METH_VARARGS, doc_set_completer}, {"get_completer", get_completer, METH_NOARGS, doc_get_completer}, + {"get_completion_type", get_completion_type, + METH_NOARGS, doc_get_completion_type}, {"get_begidx", get_begidx, METH_NOARGS, doc_get_begidx}, {"get_endidx", get_endidx, METH_NOARGS, doc_get_endidx}, @@ -560,6 +589,8 @@ {"get_completer_delims", get_completer_delims, METH_NOARGS, doc_get_completer_delims}, + {"set_completion_display_matches_hook", set_completion_display_matches_hook, + METH_VARARGS, doc_set_completion_display_matches_hook}, {"set_startup_hook", set_startup_hook, METH_VARARGS, doc_set_startup_hook}, #ifdef HAVE_RL_PRE_INPUT_HOOK @@ -623,6 +654,48 @@ #endif +/* C function to call the Python completion_display_matches */ + +static void +on_completion_display_matches_hook(char **matches, + int num_matches, int max_length) +{ + if (completion_display_matches_hook != NULL) { + int i; + PyObject *m, *s; + PyObject *r; +#ifdef WITH_THREAD + PyGILState_STATE gilstate = PyGILState_Ensure(); +#endif + m = PyList_New(num_matches); + for (i = 0; i < num_matches; i++) { + s = PyString_FromString(matches[i+1]); + PyList_SetItem(m, i, s); + } + + r = PyObject_CallFunction(completion_display_matches_hook, + "sOi", matches[0], m, max_length); + + Py_DECREF(m); + + if (r == NULL || + (r != Py_None && PyInt_AsLong(r) == -1 && PyErr_Occurred())) { + goto error; + } + + Py_DECREF(r); + goto done; + error: + PyErr_Clear(); + Py_XDECREF(r); + done: +#ifdef WITH_THREAD + PyGILState_Release(gilstate); +#endif + } +} + + /* C function to call the Python completer. */ static char * @@ -700,6 +773,8 @@ rl_bind_key_in_map ('\t', rl_complete, emacs_meta_keymap); rl_bind_key_in_map ('\033', rl_complete, emacs_meta_keymap); /* Set our hook functions */ + rl_completion_display_matches_hook = + (rl_compdisp_func_t *)on_completion_display_matches_hook; rl_startup_hook = (Function *)on_startup_hook; #ifdef HAVE_RL_PRE_INPUT_HOOK rl_pre_input_hook = (Function *)on_pre_input_hook;