changeset 4417:c16602758d84 v7.3.957

updated for version 7.3.957 Problem: Python does not have a "do" command like Perl or Lua. Solution: Add the ":py3do" command. (Lilydjwg)
author Bram Moolenaar <bram@vim.org>
date Wed, 15 May 2013 18:28:13 +0200
parents 10d658ff749f
children 083cca6a05bc
files runtime/doc/if_pyth.txt src/ex_cmds.h src/ex_docmd.c src/if_python3.c src/proto/if_python3.pro src/version.c
diffstat 6 files changed, 133 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/if_pyth.txt
+++ b/runtime/doc/if_pyth.txt
@@ -490,6 +490,21 @@ if the `:py3` command is working: >
 <							*:py3file*
 The |:py3file| command works similar to |:pyfile|.
 
+							*:py3do*
+:[range]py3do {body}	Execute Python function "def _vim_pydo(line, linenr):
+			{body}" for each line in the [range], with the
+			function arguments being set to the text of each line
+			in turn, without a trailing <EOL>, and the current
+			line number. The function should return a string or
+			None. If a string is returned, it becomes the text of
+			the line in the current turn. The default for [range]
+			is the whole file: "1,$".
+			{not in Vi}
+
+Examples:
+>
+	:py3do return "%s\t%d" % (line[::-1], len(line))
+	:py3do if line: return "%4d: %s" % (linenr, line)
 
 Vim can be built in four ways (:version output):
 1. No Python support	    (-python, -python3)
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -743,6 +743,8 @@ EX(CMD_pyfile,		"pyfile",	ex_pyfile,
 			RANGE|FILE1|NEEDARG|CMDWIN),
 EX(CMD_py3,		"py3",		ex_py3,
 			RANGE|EXTRA|NEEDARG|CMDWIN),
+EX(CMD_py3do,		"py3do",	ex_py3do,
+			RANGE|DFLALL|EXTRA|NEEDARG|CMDWIN),
 EX(CMD_python3,		"python3",	ex_py3,
 			RANGE|EXTRA|NEEDARG|CMDWIN),
 EX(CMD_py3file,		"py3file",	ex_py3file,
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -272,6 +272,7 @@ static void	ex_popup __ARGS((exarg_T *ea
 #endif
 #ifndef FEAT_PYTHON3
 # define ex_py3			ex_script_ni
+# define ex_py3do		ex_ni
 # define ex_py3file		ex_ni
 #endif
 #ifndef FEAT_TCL
--- a/src/if_python3.c
+++ b/src/if_python3.c
@@ -76,6 +76,7 @@ static void init_structs(void);
 #else
 # define CODEC_ERROR_HANDLER NULL
 #endif
+#define DOPY_FUNC "_vim_pydo"
 
 /* Python 3 does not support CObjects, always use Capsules */
 #define PY_USE_CAPSULE
@@ -126,6 +127,7 @@ static void init_structs(void);
 # define PyErr_PrintEx py3_PyErr_PrintEx
 # define PyErr_NoMemory py3_PyErr_NoMemory
 # define PyErr_Occurred py3_PyErr_Occurred
+# define PyErr_PrintEx py3_PyErr_PrintEx
 # define PyErr_SetNone py3_PyErr_SetNone
 # define PyErr_SetString py3_PyErr_SetString
 # define PyErr_SetObject py3_PyErr_SetObject
@@ -148,7 +150,6 @@ static void init_structs(void);
 # define PyTuple_GetItem py3_PyTuple_GetItem
 # define PySlice_GetIndicesEx py3_PySlice_GetIndicesEx
 # define PyImport_ImportModule py3_PyImport_ImportModule
-# define PyImport_AddModule py3_PyImport_AddModule
 # define PyObject_Init py3__PyObject_Init
 # define PyDict_New py3_PyDict_New
 # define PyDict_GetItemString py3_PyDict_GetItemString
@@ -163,6 +164,11 @@ static void init_structs(void);
 # define PyRun_SimpleString py3_PyRun_SimpleString
 #undef PyRun_String
 # define PyRun_String py3_PyRun_String
+# define PyObject_GetAttrString py3_PyObject_GetAttrString
+# define PyObject_SetAttrString py3_PyObject_SetAttrString
+# define PyObject_CallFunctionObjArgs py3_PyObject_CallFunctionObjArgs
+# define PyEval_GetLocals py3_PyEval_GetLocals
+# define PyEval_GetGlobals py3_PyEval_GetGlobals
 # define PySys_SetObject py3_PySys_SetObject
 # define PySys_SetArgv py3_PySys_SetArgv
 # define PyType_Ready py3_PyType_Ready
@@ -178,6 +184,7 @@ static void init_structs(void);
 # define _PyObject_NextNotImplemented (*py3__PyObject_NextNotImplemented)
 # define PyModule_AddObject py3_PyModule_AddObject
 # define PyImport_AppendInittab py3_PyImport_AppendInittab
+# define PyImport_AddModule py3_PyImport_AddModule
 # if PY_VERSION_HEX >= 0x030300f0
 #  undef _PyUnicode_AsString
 #  define _PyUnicode_AsString py3_PyUnicode_AsUTF8
@@ -254,6 +261,11 @@ static void (*py3_PyErr_SetString)(PyObj
 static void (*py3_PyErr_SetObject)(PyObject *, PyObject *);
 static int (*py3_PyRun_SimpleString)(char *);
 static PyObject* (*py3_PyRun_String)(char *, int, PyObject *, PyObject *);
+static PyObject* (*py3_PyObject_GetAttrString)(PyObject *, const char *);
+static PyObject* (*py3_PyObject_SetAttrString)(PyObject *, const char *, PyObject *);
+static PyObject* (*py3_PyObject_CallFunctionObjArgs)(PyObject *, ...);
+static PyObject* (*py3_PyEval_GetGlobals)();
+static PyObject* (*py3_PyEval_GetLocals)();
 static PyObject* (*py3_PyList_GetItem)(PyObject *, Py_ssize_t);
 static PyObject* (*py3_PyImport_ImportModule)(const char *);
 static PyObject* (*py3_PyImport_AddModule)(const char *);
@@ -386,6 +398,11 @@ static struct
     {"PyErr_SetObject", (PYTHON_PROC*)&py3_PyErr_SetObject},
     {"PyRun_SimpleString", (PYTHON_PROC*)&py3_PyRun_SimpleString},
     {"PyRun_String", (PYTHON_PROC*)&py3_PyRun_String},
+    {"PyObject_GetAttrString", (PYTHON_PROC*)&py3_PyObject_GetAttrString},
+    {"PyObject_SetAttrString", (PYTHON_PROC*)&py3_PyObject_SetAttrString},
+    {"PyObject_CallFunctionObjArgs", (PYTHON_PROC*)&py3_PyObject_CallFunctionObjArgs},
+    {"PyEval_GetGlobals", (PYTHON_PROC*)&py3_PyEval_GetGlobals},
+    {"PyEval_GetLocals", (PYTHON_PROC*)&py3_PyEval_GetLocals},
     {"PyList_GetItem", (PYTHON_PROC*)&py3_PyList_GetItem},
     {"PyImport_ImportModule", (PYTHON_PROC*)&py3_PyImport_ImportModule},
     {"PyImport_AddModule", (PYTHON_PROC*)&py3_PyImport_AddModule},
@@ -990,6 +1007,100 @@ ex_py3file(exarg_T *eap)
     DoPy3Command(eap, buffer, NULL);
 }
 
+void ex_py3do(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 (Python3_Init())
+	goto theend;
+
+    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, *pybytes;
+
+	line = (char *)ml_get(i);
+	pygilstate = PyGILState_Ensure();
+	pyline = PyUnicode_Decode(line, strlen(line),
+		(char *)ENC_OPT, CODEC_ERROR_HANDLER);
+	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 (!PyUnicode_Check(pyret))
+	    {
+		/* TODO: a proper error number */
+		EMSG(_("E000: return value must be an instance of str"));
+		Py_XDECREF(pyret);
+		status = 1;
+		goto out;
+	    }
+	    pybytes = PyUnicode_AsEncodedString(pyret,
+		    (char *)ENC_OPT, CODEC_ERROR_HANDLER);
+	    ml_replace(i, (char_u *) PyBytes_AsString(pybytes), 1);
+	    Py_DECREF(pybytes);
+	    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);
+
+theend:
+    return;
+}
+
 /******************************************************
  * 2. Python output stream: writes output via [e]msg().
  */
--- a/src/proto/if_python3.pro
+++ b/src/proto/if_python3.pro
@@ -3,6 +3,7 @@ int python3_enabled __ARGS((int verbose)
 void python3_end __ARGS((void));
 int python3_loaded __ARGS((void));
 void ex_py3 __ARGS((exarg_T *eap));
+void ex_py3do __ARGS((exarg_T *eap));
 void ex_py3file __ARGS((exarg_T *eap));
 void python3_buffer_free __ARGS((buf_T *buf));
 void python3_window_free __ARGS((win_T *win));
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    957,
+/**/
     956,
 /**/
     955,