diff options
author | Ronald Oussoren <ronaldoussoren@mac.com> | 2009-09-20 14:18:15 (GMT) |
---|---|---|
committer | Ronald Oussoren <ronaldoussoren@mac.com> | 2009-09-20 14:18:15 (GMT) |
commit | 9f20d9d0ee78f7bd810dfe788a8d1319afbc36e7 (patch) | |
tree | 139e1f5b7e05f8504457db5d9a595e5ffb727966 /Modules | |
parent | 956f4b2520ef921daa3ab1083d56d74317505c2e (diff) | |
download | cpython-9f20d9d0ee78f7bd810dfe788a8d1319afbc36e7.zip cpython-9f20d9d0ee78f7bd810dfe788a8d1319afbc36e7.tar.gz cpython-9f20d9d0ee78f7bd810dfe788a8d1319afbc36e7.tar.bz2 |
Issue 6877: this patch makes it possible to link the readline extension
to the libedit emulation of the readline API on OSX 10.5 or later.
This also adds a minimal testsuite for readline to check that the
history manipuation functions have the same interface with both
C libraries.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/readline.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/Modules/readline.c b/Modules/readline.c index d09f09c..67f4631 100644 --- a/Modules/readline.c +++ b/Modules/readline.c @@ -42,6 +42,25 @@ extern char **completion_matches(char *, CPFunction *); #endif #endif +#ifdef __APPLE__ +/* + * It is possible to link the readline module to the readline + * emulation library of editline/libedit. + * + * On OSX this emulation library is not 100% API compatible + * with the "real" readline and cannot be detected at compile-time, + * hence we use a runtime check to detect if we're using libedit + * + * Currently there is one know API incompatibility: + * - 'get_history' has a 1-based index with GNU readline, and a 0-based + * index with libedit's emulation. + * - Note that replace_history and remove_history use a 0-based index + * with both implementation. + */ +static int using_libedit_emulation = 0; +static const char libedit_version_tag[] = "EditLine wrapper"; +#endif /* __APPLE__ */ + static void on_completion_display_matches_hook(char **matches, int num_matches, int max_length); @@ -478,6 +497,29 @@ get_history_item(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "i:index", &idx)) return NULL; +#ifdef __APPLE__ + if (using_libedit_emulation) { + /* Libedit emulation uses 0-based indexes, + * the real one uses 1-based indexes, + * adjust the index to ensure that Python + * code doesn't have to worry about the + * difference. + */ + HISTORY_STATE *hist_st; + hist_st = history_get_history_state(); + + idx --; + + /* + * Apple's readline emulation crashes when + * the index is out of range, therefore + * test for that and fail gracefully. + */ + if (idx < 0 || idx >= hist_st->length) { + Py_RETURN_NONE; + } + } +#endif /* __APPLE__ */ if ((hist_ent = history_get(idx))) return PyString_FromString(hist_ent->line); else { @@ -978,6 +1020,15 @@ call_readline(FILE *sys_stdin, FILE *sys_stdout, char *prompt) char *line; HISTORY_STATE *state = history_get_history_state(); if (state->length > 0) +#ifdef __APPLE__ + if (using_libedit_emulation) { + /* + * Libedit's emulation uses 0-based indexes, + * the real readline uses 1-based indexes. + */ + line = history_get(state->length - 1)->line; + } else +#endif /* __APPLE__ */ line = history_get(state->length)->line; else line = ""; @@ -1011,16 +1062,35 @@ call_readline(FILE *sys_stdin, FILE *sys_stdout, char *prompt) PyDoc_STRVAR(doc_module, "Importing this module enables command line editing using GNU readline."); +#ifdef __APPLE__ +PyDoc_STRVAR(doc_module_le, +"Importing this module enables command line editing using libedit readline."); +#endif /* __APPLE__ */ + PyMODINIT_FUNC initreadline(void) { PyObject *m; +#ifdef __APPLE__ + if (strncmp(rl_library_version, libedit_version_tag, strlen(libedit_version_tag)) == 0) { + using_libedit_emulation = 1; + } + + if (using_libedit_emulation) + m = Py_InitModule4("readline", readline_methods, doc_module_le, + (PyObject *)NULL, PYTHON_API_VERSION); + else + +#endif /* __APPLE__ */ + m = Py_InitModule4("readline", readline_methods, doc_module, (PyObject *)NULL, PYTHON_API_VERSION); if (m == NULL) return; + + PyOS_ReadlineFunctionPointer = call_readline; setup_readline(); } |