diff src/if_python.c @ 4435:9b800f0a757f v7.3.966

updated for version 7.3.966 Problem: There is ":py3do" but no ":pydo". Solution: Add the ":pydo" command. (Lilydjwg)
author Bram Moolenaar <bram@vim.org>
date Fri, 17 May 2013 16:40:06 +0200
parents 7d81f4e96728
children 8fe768bc1234
line wrap: on
line diff
--- a/src/if_python.c
+++ b/src/if_python.c
@@ -198,6 +198,9 @@ struct PyMethodDef { Py_ssize_t a; };
 # define PyModule_GetDict dll_PyModule_GetDict
 # define PyRun_SimpleString dll_PyRun_SimpleString
 # define PyRun_String dll_PyRun_String
+# define PyObject_GetAttrString dll_PyObject_GetAttrString
+# define PyObject_SetAttrString dll_PyObject_SetAttrString
+# define PyObject_CallFunctionObjArgs dll_PyObject_CallFunctionObjArgs
 # define PyString_AsString dll_PyString_AsString
 # define PyString_AsStringAndSize dll_PyString_AsStringAndSize
 # define PyString_FromString dll_PyString_FromString
@@ -303,6 +306,9 @@ static PyObject* (*dll_PyIter_Next)(PyOb
 static PyObject*(*dll_PyModule_GetDict)(PyObject *);
 static int(*dll_PyRun_SimpleString)(char *);
 static PyObject *(*dll_PyRun_String)(char *, int, PyObject *, PyObject *);
+static PyObject* (*dll_PyObject_GetAttrString)(PyObject *, const char *);
+static PyObject* (*dll_PyObject_SetAttrString)(PyObject *, const char *, PyObject *);
+static PyObject* (*dll_PyObject_CallFunctionObjArgs)(PyObject *, ...);
 static char*(*dll_PyString_AsString)(PyObject *);
 static int(*dll_PyString_AsStringAndSize)(PyObject *, char **, int *);
 static PyObject*(*dll_PyString_FromString)(const char *);
@@ -440,6 +446,9 @@ static struct
     {"PyModule_GetDict", (PYTHON_PROC*)&dll_PyModule_GetDict},
     {"PyRun_SimpleString", (PYTHON_PROC*)&dll_PyRun_SimpleString},
     {"PyRun_String", (PYTHON_PROC*)&dll_PyRun_String},
+    {"PyObject_GetAttrString", (PYTHON_PROC*)&dll_PyObject_GetAttrString},
+    {"PyObject_SetAttrString", (PYTHON_PROC*)&dll_PyObject_SetAttrString},
+    {"PyObject_CallFunctionObjArgs", (PYTHON_PROC*)&dll_PyObject_CallFunctionObjArgs},
     {"PyString_AsString", (PYTHON_PROC*)&dll_PyString_AsString},
     {"PyString_AsStringAndSize", (PYTHON_PROC*)&dll_PyString_AsStringAndSize},
     {"PyString_FromString", (PYTHON_PROC*)&dll_PyString_FromString},
@@ -995,6 +1004,93 @@ ex_pyfile(exarg_T *eap)
     DoPythonCommand(eap, buffer, NULL);
 }
 
+    void
+ex_pydo(exarg_T *eap)
+{
+    linenr_T		i;
+    const char		*code_hdr = "def " DOPY_FUNC "(line, linenr):\n ";
+    const char		*s = (const char *) eap->arg;
+    size_t		len;
+    char		*code;
+    int			status;
+    PyObject		*pyfunc, *pymain;
+    PyGILState_STATE	pygilstate;
+
+    if (Python_Init())
+        return;
+
+    if (u_save(eap->line1 - 1, eap->line2 + 1) != OK)
+    {
+	EMSG(_("cannot save undo information"));
+	return;
+    }
+    len = strlen(code_hdr) + strlen(s);
+    code = malloc(len + 1);
+    STRCPY(code, code_hdr);
+    STRNCAT(code, s, len + 1);
+    pygilstate = PyGILState_Ensure();
+    status = PyRun_SimpleString(code);
+    vim_free(code);
+    if (status)
+    {
+	EMSG(_("failed to run the code"));
+	return;
+    }
+    status = 0; /* good */
+    pymain = PyImport_AddModule("__main__");
+    pyfunc = PyObject_GetAttrString(pymain, DOPY_FUNC);
+    PyGILState_Release(pygilstate);
+
+    for (i = eap->line1; i <= eap->line2; i++)
+    {
+	const char *line;
+	PyObject *pyline, *pylinenr, *pyret;
+
+	line = (char *)ml_get(i);
+	pygilstate = PyGILState_Ensure();
+	pyline = PyString_FromStringAndSize(line, strlen(line));
+	pylinenr = PyLong_FromLong(i);
+	pyret = PyObject_CallFunctionObjArgs(pyfunc, pyline, pylinenr, NULL);
+	Py_DECREF(pyline);
+	Py_DECREF(pylinenr);
+	if (!pyret)
+	{
+	    PyErr_PrintEx(0);
+	    PythonIO_Flush();
+	    status = 1;
+	    goto out;
+	}
+
+	if (pyret && pyret != Py_None)
+	{
+	    if (!PyString_Check(pyret))
+	    {
+		EMSG(_("E863: return value must be an instance of str"));
+		Py_XDECREF(pyret);
+		status = 1;
+		goto out;
+	    }
+	    ml_replace(i, (char_u *) PyString_AsString(pyret), 1);
+	    changed();
+#ifdef SYNTAX_HL
+	    syn_changed(i); /* recompute syntax hl. for this line */
+#endif
+	}
+	Py_XDECREF(pyret);
+	PythonIO_Flush();
+	PyGILState_Release(pygilstate);
+    }
+    pygilstate = PyGILState_Ensure();
+out:
+    Py_DECREF(pyfunc);
+    PyObject_SetAttrString(pymain, DOPY_FUNC, NULL);
+    PyGILState_Release(pygilstate);
+    if (status)
+	return;
+    check_cursor();
+    update_curbuf(NOT_VALID);
+}
+
 /******************************************************
  * 2. Python output stream: writes output via [e]msg().
  */