From 0969d362751bd779fc6618d70ddd6c76e8cbc12c Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Tue, 5 Aug 1997 21:27:50 +0000 Subject: [PATCH] New mechanism for GNU readline interface, via module --- Modules/Setup.in | 10 ++++ Modules/_tkinter.c | 12 ++--- Modules/readline.c | 122 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+), 9 deletions(-) create mode 100644 Modules/readline.c diff --git a/Modules/Setup.in b/Modules/Setup.in index 6acfa885e62..bb06b11ab7a 100644 --- a/Modules/Setup.in +++ b/Modules/Setup.in @@ -120,6 +120,16 @@ signal signalmodule.c # signal(2) #*shared* +# GNU readline. Unlike previous Python incarnations, GNU readline is +# now incorporated in an optional module, configured in the Setup file +# instead of by a configure script switch. You may have to insert a +# -L option pointing to the directory where libreadline.* lives, +# and you may have to change -ltermcap to -ltermlib or perhaps remove +# it, depending on your system -- see the GNU readline instructions. +# It's okay for this to be a shared library, too. + +#readline readline.c -lreadline -ltermcap + # Modules that should always be present (non UNIX dependent): diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index 528c2296a81..1f32c4a492f 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -1428,11 +1428,9 @@ static PyMethodDef moduleMethods[] = {NULL, NULL} }; -#ifdef WITH_READLINE static int EventHook() { - /* XXX Reset tty */ if (errorInCmd) { errorInCmd = 0; PyErr_Restore(excInCmd, valInCmd, trbInCmd); @@ -1443,7 +1441,6 @@ EventHook() Tcl_DoOneEvent(TCL_DONT_WAIT); return 0; } -#endif /* WITH_READLINE */ /* all errors will be checked in one fell swoop in init_tkinter() */ @@ -1476,9 +1473,7 @@ ins_string(d, name, val) void init_tkinter() { -#ifdef WITH_READLINE - extern int (*rl_event_hook) (); -#endif /* WITH_READLINE */ + extern int (*Py_input_hook) (); PyObject *m, *d; Tkapp_Type.ob_type = &PyType_Type; @@ -1502,9 +1497,8 @@ init_tkinter() ins_string(d, "TK_VERSION", TK_VERSION); ins_string(d, "TCL_VERSION", TCL_VERSION); -#ifdef WITH_READLINE - rl_event_hook = EventHook; -#endif /* WITH_READLINE */ + if (Py_input_hook == NULL) + Py_input_hook = EventHook; if (PyErr_Occurred()) Py_FatalError("can't initialize module _tkinter"); diff --git a/Modules/readline.c b/Modules/readline.c new file mode 100644 index 00000000000..8927630eb0b --- /dev/null +++ b/Modules/readline.c @@ -0,0 +1,122 @@ +/* The readline module makes GNU readline available to Python. It + * has ideas contributed by Lee Busby, LLNL, and William Magro, + * Cornell Theory Center. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "Python.h" +#include +#include + +/* Routines needed from outside (but not declared in a header file). */ +extern int (*Py_input_hook)(); +extern char *readline(); +extern int rl_initialize(); +extern int rl_insert(); +extern int rl_bind_key(); +extern void add_history(); +extern char *rl_readline_name; +extern int (*rl_event_hook)(); +extern char *(*PyOS_ReadlineFunctionPointer) Py_PROTO((char *)); + +/* This module's initialization routine */ +void initreadline (void); + +static void PyOS_ReadlineInit(); +static RETSIGTYPE onintr(); +static char *PyOS_GnuReadline(); +static jmp_buf jbuf; +static PyObject *ReadlineError; +static int already_initialized = 0; +static char readline_module_documentation[] = +"Readline Module, version0.0" +; + +static struct PyMethodDef readline_methods[] = +{ + { 0, 0 } +}; + +/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ + +/* Initialize the module. Actually, that's all you can or need to do. */ +void initreadline (void) +{ + PyObject *m, *d; + + if (already_initialized) + return; + m = Py_InitModule4 ("readline", readline_methods, + readline_module_documentation, + (PyObject *) 0, PYTHON_API_VERSION); + d = PyModule_GetDict (m); + ReadlineError = PyString_FromString ("Readline.error"); + PyDict_SetItemString (d, "error", ReadlineError); + if (PyErr_Occurred ()) { + Py_FatalError ("Cannot initialize module readline"); + } + if (isatty(fileno(stdin))){ + PyOS_ReadlineFunctionPointer = PyOS_GnuReadline; + PyOS_ReadlineInit(); + } + already_initialized = 1; +} + +/* ARGSUSED */ +static RETSIGTYPE +onintr(sig) + int sig; +{ + longjmp(jbuf, 1); +} + +static void +PyOS_ReadlineInit() +{ + /* Force rebind of TAB to insert-tab */ + rl_readline_name = "python"; + rl_initialize(); + rl_bind_key('\t', rl_insert); +} + +static char * +PyOS_GnuReadline(prompt) + char *prompt; +{ + int n; + char *p; + RETSIGTYPE (*old_inthandler)(); + old_inthandler = signal(SIGINT, onintr); + if (setjmp(jbuf)) { +#ifdef HAVE_SIGRELSE + /* This seems necessary on SunOS 4.1 (Rasmus Hahn) */ + sigrelse(SIGINT); +#endif + signal(SIGINT, old_inthandler); + return NULL; + } + rl_event_hook = Py_input_hook; + p = readline(prompt); + signal(SIGINT, old_inthandler); + if (p == NULL) { + p = malloc(1); + if (p != NULL) + *p = '\0'; + return p; + } + n = strlen(p); + if (n > 0) + add_history(p); + if ((p = realloc(p, n+2)) != NULL) { + p[n] = '\n'; + p[n+1] = '\0'; + } + return p; +} + +#ifdef __cplusplus +} +#endif