summaryrefslogtreecommitdiffstats
path: root/Modules/readline.c
diff options
context:
space:
mode:
authorRonald Oussoren <ronaldoussoren@mac.com>2009-09-20 14:53:22 (GMT)
committerRonald Oussoren <ronaldoussoren@mac.com>2009-09-20 14:53:22 (GMT)
commit2efd9247549064887b0206d4a57d2abda03384e8 (patch)
treeabc5516ea2c01ad39b789f03f1187a2df483bada /Modules/readline.c
parentf172f31e4f1ad74e31215138e56327af118603ef (diff)
downloadcpython-2efd9247549064887b0206d4a57d2abda03384e8.zip
cpython-2efd9247549064887b0206d4a57d2abda03384e8.tar.gz
cpython-2efd9247549064887b0206d4a57d2abda03384e8.tar.bz2
Merged revisions 74970 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r74970 | ronald.oussoren | 2009-09-20 16:18:15 +0200 (Sun, 20 Sep 2009) | 7 lines 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/readline.c')
-rw-r--r--Modules/readline.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/Modules/readline.c b/Modules/readline.c
index 8925d8d..03c95e3 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 PyUnicode_FromString(hist_ent->line);
else {
@@ -977,6 +1019,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 = "";
@@ -1010,6 +1061,10 @@ 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__ */
static struct PyModuleDef readlinemodule = {
PyModuleDef_HEAD_INIT,
@@ -1023,15 +1078,29 @@ static struct PyModuleDef readlinemodule = {
NULL
};
+
PyMODINIT_FUNC
PyInit_readline(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)
+ readlinemodule.m_doc = doc_module_le;
+
+#endif /* __APPLE__ */
+
m = PyModule_Create(&readlinemodule);
+
if (m == NULL)
return NULL;
+
+
PyOS_ReadlineFunctionPointer = call_readline;
setup_readline();
return m;