New mechanism for GNU readline interface, via module

This commit is contained in:
Guido van Rossum 1997-08-05 21:27:50 +00:00
parent 570278be6e
commit 0969d36275
3 changed files with 135 additions and 9 deletions

View File

@ -120,6 +120,16 @@ signal signalmodule.c # signal(2)
#*shared* #*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): # Modules that should always be present (non UNIX dependent):

View File

@ -1428,11 +1428,9 @@ static PyMethodDef moduleMethods[] =
{NULL, NULL} {NULL, NULL}
}; };
#ifdef WITH_READLINE
static int static int
EventHook() EventHook()
{ {
/* XXX Reset tty */
if (errorInCmd) { if (errorInCmd) {
errorInCmd = 0; errorInCmd = 0;
PyErr_Restore(excInCmd, valInCmd, trbInCmd); PyErr_Restore(excInCmd, valInCmd, trbInCmd);
@ -1443,7 +1441,6 @@ EventHook()
Tcl_DoOneEvent(TCL_DONT_WAIT); Tcl_DoOneEvent(TCL_DONT_WAIT);
return 0; return 0;
} }
#endif /* WITH_READLINE */
/* all errors will be checked in one fell swoop in init_tkinter() */ /* all errors will be checked in one fell swoop in init_tkinter() */
@ -1476,9 +1473,7 @@ ins_string(d, name, val)
void void
init_tkinter() init_tkinter()
{ {
#ifdef WITH_READLINE extern int (*Py_input_hook) ();
extern int (*rl_event_hook) ();
#endif /* WITH_READLINE */
PyObject *m, *d; PyObject *m, *d;
Tkapp_Type.ob_type = &PyType_Type; Tkapp_Type.ob_type = &PyType_Type;
@ -1502,9 +1497,8 @@ init_tkinter()
ins_string(d, "TK_VERSION", TK_VERSION); ins_string(d, "TK_VERSION", TK_VERSION);
ins_string(d, "TCL_VERSION", TCL_VERSION); ins_string(d, "TCL_VERSION", TCL_VERSION);
#ifdef WITH_READLINE if (Py_input_hook == NULL)
rl_event_hook = EventHook; Py_input_hook = EventHook;
#endif /* WITH_READLINE */
if (PyErr_Occurred()) if (PyErr_Occurred())
Py_FatalError("can't initialize module _tkinter"); Py_FatalError("can't initialize module _tkinter");

122
Modules/readline.c Normal file
View File

@ -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 <setjmp.h>
#include <signal.h>
/* 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