[Python-checkins] CVS: python/dist/src/Modules readline.c,2.37,2.38
Martin v. L?wis
loewis@users.sourceforge.net
Sun, 30 Sep 2001 14:10:01 -0700
Update of /cvsroot/python/python/dist/src/Modules
In directory usw-pr-cvs1:/tmp/cvs-serv18073/Modules
Modified Files:
readline.c
Log Message:
Patch #462122: add readline startup and pre_event hooks.
Index: readline.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/readline.c,v
retrieving revision 2.37
retrieving revision 2.38
diff -C2 -d -r2.37 -r2.38
*** readline.c 2001/08/01 21:44:14 2.37
--- readline.c 2001/09/30 21:09:59 2.38
***************
*** 159,168 ****
}
/* Exported function to specify a word completer in Python */
static PyObject *completer = NULL;
! static PyThreadState *tstate = NULL;
static PyObject *begidx = NULL;
--- 159,236 ----
}
+ /* Generic hook function setter */
+
+ static PyObject *
+ set_hook(const char * funcname, PyObject **hook_var, PyThreadState **tstate, PyObject *args)
+ {
+ PyObject *function = Py_None;
+ char buf[80];
+ sprintf(buf, "|O:set_%s", funcname);
+ if (!PyArg_ParseTuple(args, buf, &function))
+ return NULL;
+ if (function == Py_None) {
+ Py_XDECREF(*hook_var);
+ *hook_var = NULL;
+ *tstate = NULL;
+ }
+ else if (PyCallable_Check(function)) {
+ PyObject *tmp = *hook_var;
+ Py_INCREF(function);
+ *hook_var = function;
+ Py_XDECREF(tmp);
+ *tstate = PyThreadState_Get();
+ }
+ else {
+ sprintf(buf, "set_%s(func): argument not callable", funcname);
+ PyErr_SetString(PyExc_TypeError, buf);
+ return NULL;
+ }
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ /* Exported functions to specify hook functions in Python */
+
+ static PyObject *startup_hook = NULL;
+ static PyThreadState *startup_hook_tstate = NULL;
+
+ #ifdef HAVE_RL_PRE_INPUT_HOOK
+ static PyObject *pre_input_hook = NULL;
+ static PyThreadState *pre_input_hook_tstate = NULL;
+ #endif
+
+ static PyObject *
+ set_startup_hook(PyObject *self, PyObject *args)
+ {
+ return set_hook("startup_hook", &startup_hook, &startup_hook_tstate, args);
+ }
+
+ static char doc_set_startup_hook[] = "\
+ set_startup_hook([function]) -> None\n\
+ Set or remove the startup_hook function.\n\
+ The function is called with no arguments just\n\
+ before readline prints the first prompt.\n\
+ ";
+
+ #ifdef HAVE_RL_PRE_INPUT_HOOK
+ static PyObject *
+ set_pre_input_hook(PyObject *self, PyObject *args)
+ {
+ return set_hook("pre_input_hook", &pre_input_hook, &pre_input_hook_tstate, args);
+ }
+ static char doc_set_pre_input_hook[] = "\
+ set_pre_input_hook([function]) -> None\n\
+ Set or remove the pre_input_hook function.\n\
+ The function is called with no arguments after the first prompt\n\
+ has been printed and just before readline starts reading input\n\
+ characters.\n\
+ ";
+ #endif
/* Exported function to specify a word completer in Python */
static PyObject *completer = NULL;
! static PyThreadState *completer_tstate = NULL;
static PyObject *begidx = NULL;
***************
*** 239,264 ****
set_completer(PyObject *self, PyObject *args)
{
! PyObject *function = Py_None;
! if (!PyArg_ParseTuple(args, "|O:set_completer", &function))
! return NULL;
! if (function == Py_None) {
! Py_XDECREF(completer);
! completer = NULL;
! tstate = NULL;
! }
! else if (PyCallable_Check(function)) {
! PyObject *tmp = completer;
! Py_INCREF(function);
! completer = function;
! Py_XDECREF(tmp);
! tstate = PyThreadState_Get();
! }
! else {
! PyErr_SetString(PyExc_TypeError,
! "set_completer(func): argument not callable");
! return NULL;
! }
! Py_INCREF(Py_None);
! return Py_None;
}
--- 307,311 ----
set_completer(PyObject *self, PyObject *args)
{
! return set_hook("completer", &completer, &completer_tstate, args);
}
***************
*** 331,337 ****
--- 378,435 ----
{"get_completer_delims", get_completer_delims,
METH_OLDARGS, doc_get_completer_delims},
+
+ {"set_startup_hook", set_startup_hook, METH_VARARGS, doc_set_startup_hook},
+ #ifdef HAVE_RL_PRE_INPUT_HOOK
+ {"set_pre_input_hook", set_pre_input_hook, METH_VARARGS, doc_set_pre_input_hook},
+ #endif
{0, 0}
};
+ /* C function to call the Python hooks. */
+
+ static int
+ on_hook(PyObject *func, PyThreadState *tstate)
+ {
+ int result = 0;
+ if (func != NULL) {
+ PyObject *r;
+ PyThreadState *save_tstate;
+ /* Note that readline is called with the interpreter
+ lock released! */
+ save_tstate = PyThreadState_Swap(NULL);
+ PyEval_RestoreThread(tstate);
+ r = PyObject_CallFunction(func, NULL);
+ if (r == NULL)
+ goto error;
+ if (r == Py_None)
+ result = 0;
+ else
+ result = PyInt_AsLong(r);
+ Py_DECREF(r);
+ goto done;
+ error:
+ PyErr_Clear();
+ Py_XDECREF(r);
+ done:
+ PyEval_SaveThread();
+ PyThreadState_Swap(save_tstate);
+ }
+ return result;
+ }
+
+ static int
+ on_startup_hook(void)
+ {
+ return on_hook(startup_hook, startup_hook_tstate);
+ }
+
+ #ifdef HAVE_RL_PRE_INPUT_HOOK
+ static int
+ on_pre_input_hook(void)
+ {
+ return on_hook(pre_input_hook, pre_input_hook_tstate);
+ }
+ #endif
+
/* C function to call the Python completer. */
***************
*** 346,350 ****
lock released! */
save_tstate = PyThreadState_Swap(NULL);
! PyEval_RestoreThread(tstate);
r = PyObject_CallFunction(completer, "si", text, state);
if (r == NULL)
--- 444,448 ----
lock released! */
save_tstate = PyThreadState_Swap(NULL);
! PyEval_RestoreThread(completer_tstate);
r = PyObject_CallFunction(completer, "si", text, state);
if (r == NULL)
***************
*** 396,399 ****
--- 494,502 ----
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_startup_hook = (Function *)on_startup_hook;
+ #ifdef HAVE_RL_PRE_INPUT_HOOK
+ rl_pre_input_hook = (Function *)on_pre_input_hook;
+ #endif
/* Set our completion function */
rl_attempted_completion_function = (CPPFunction *)flex_complete;