diff --git a/Doc/library/readline.rst b/Doc/library/readline.rst index 9a40747b4f2..812586271d8 100644 --- a/Doc/library/readline.rst +++ b/Doc/library/readline.rst @@ -142,6 +142,12 @@ The :mod:`readline` module defines the following functions: .. versionadded:: 2.3 +.. function:: get_completion_type() + + Get the type of completion being attempted. + + .. versionadded:: 2.6 + .. function:: get_begidx() Get the beginning index of the readline tab-completion scope. @@ -161,6 +167,16 @@ The :mod:`readline` module defines the following functions: Get the readline word delimiters for tab-completion. +.. function:: set_completion_display_matches_hook([function]) + + Set or remove the completion display function. If *function* is + specified, it will be used as the new completion display function; + if omitted or ``None``, any completion display function already + installed is removed. The completion display function is called as + ``function(substitution, [matches], longest_match_length)`` once + each time matches need to be displayed. + + .. versionadded:: 2.6 .. function:: add_history(line) diff --git a/Misc/ACKS b/Misc/ACKS index cbe4e6c0ffa..3d73388d476 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -80,6 +80,7 @@ Jurjen Bos Peter Bosch Eric Bouck Thierry Bousch +Sebastian Boving Monty Brandenberg Georg Brandl Terrence Brannon diff --git a/Misc/NEWS b/Misc/NEWS index 2cfc4cef5a5..f8a875c5746 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -746,6 +746,9 @@ Library Extension Modules ----------------- +- Patch #1388440: Add set_completion_display_matches_hook and + get_completion_type to readline. + - Bug #1649098: Avoid declaration of zero-sized array declaration in structure. diff --git a/Modules/readline.c b/Modules/readline.c index fd800ffa1aa..f620f6229f1 100644 --- a/Modules/readline.c +++ b/Modules/readline.c @@ -198,12 +198,27 @@ set_hook(const char *funcname, PyObject **hook_var, PyObject *args) /* 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 static PyObject *pre_input_hook = NULL; #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) { @@ -245,6 +260,18 @@ static PyObject *begidx = NULL; 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 * @@ -557,6 +584,8 @@ static struct PyMethodDef readline_methods[] = 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}, @@ -568,6 +597,8 @@ static struct PyMethodDef readline_methods[] = {"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 @@ -631,6 +662,48 @@ on_pre_input_hook(void) #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 * @@ -708,6 +781,10 @@ setup_readline(void) 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 */ +#ifdef HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK + rl_completion_display_matches_hook = + (rl_compdisp_func_t *)on_completion_display_matches_hook; +#endif rl_startup_hook = (Function *)on_startup_hook; #ifdef HAVE_RL_PRE_INPUT_HOOK rl_pre_input_hook = (Function *)on_pre_input_hook; diff --git a/configure b/configure index 4518c7d19e1..6d9862e7252 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 57762 . +# From configure.in Revision: 57904 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for python 2.6. # @@ -21699,6 +21699,77 @@ _ACEOF fi +# also in 4.0 +{ echo "$as_me:$LINENO: checking for rl_completion_display_matches_hook in -lreadline" >&5 +echo $ECHO_N "checking for rl_completion_display_matches_hook in -lreadline... $ECHO_C" >&6; } +if test "${ac_cv_lib_readline_rl_completion_display_matches_hook+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lreadline $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char rl_completion_display_matches_hook (); +int +main () +{ +return rl_completion_display_matches_hook (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_readline_rl_completion_display_matches_hook=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_readline_rl_completion_display_matches_hook=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_readline_rl_completion_display_matches_hook" >&5 +echo "${ECHO_T}$ac_cv_lib_readline_rl_completion_display_matches_hook" >&6; } +if test $ac_cv_lib_readline_rl_completion_display_matches_hook = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK 1 +_ACEOF + +fi + + # check for readline 4.2 { echo "$as_me:$LINENO: checking for rl_completion_matches in -lreadline" >&5 echo $ECHO_N "checking for rl_completion_matches in -lreadline... $ECHO_C" >&6; } diff --git a/configure.in b/configure.in index dd8e1177b46..7480ee64a14 100644 --- a/configure.in +++ b/configure.in @@ -3137,6 +3137,11 @@ AC_CHECK_LIB(readline, rl_pre_input_hook, AC_DEFINE(HAVE_RL_PRE_INPUT_HOOK, 1, [Define if you have readline 4.0]), , ) +# also in 4.0 +AC_CHECK_LIB(readline, rl_completion_display_matches_hook, + AC_DEFINE(HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK, 1, + [Define if you have readline 4.0]), , ) + # check for readline 4.2 AC_CHECK_LIB(readline, rl_completion_matches, AC_DEFINE(HAVE_RL_COMPLETION_MATCHES, 1, diff --git a/pyconfig.h.in b/pyconfig.h.in index 012bf7e0d20..16c85a591a8 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -432,6 +432,9 @@ /* Define if you have readline 2.2 */ #undef HAVE_RL_COMPLETION_APPEND_CHARACTER +/* Define if you have readline 4.0 */ +#undef HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK + /* Define if you have readline 4.2 */ #undef HAVE_RL_COMPLETION_MATCHES