summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/if_pyth.txt35
-rw-r--r--src/ex_cmds.h2
-rw-r--r--src/ex_docmd.c1
-rw-r--r--src/if_py_both.h1
-rw-r--r--src/if_python.c96
-rw-r--r--src/if_python3.c1
-rw-r--r--src/proto/if_python.pro1
-rw-r--r--src/version.c2
8 files changed, 122 insertions, 17 deletions
diff --git a/runtime/doc/if_pyth.txt b/runtime/doc/if_pyth.txt
index 051dfacaf3..a2c949e34b 100644
--- a/runtime/doc/if_pyth.txt
+++ b/runtime/doc/if_pyth.txt
@@ -57,6 +57,22 @@ Example: >
Note: Python is very sensitive to the indenting. Make sure the "class" line
and "EOF" do not have any indent.
+ *:pydo*
+:[range]pydo {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:
+>
+ :pydo return "%s\t%d" % (line[::-1], len(line))
+ :pydo if line: return "%4d: %s" % (linenr, line)
+<
*:pyfile* *:pyf*
:[range]pyf[ile] {file}
Execute the Python script in {file}. The whole
@@ -485,27 +501,14 @@ sure edit "gvim.exe" and search for "python\d*.dll\c".
8. Python 3 *python3*
*:py3* *:python3*
-The |:py3| and |:python3| commands work similar to |:python|. A simple check
+The `:py3` and `:python3` commands work similar to `:python`. A simple check
if the `:py3` command is working: >
:py3 print("Hello")
< *:py3file*
-The |:py3file| command works similar to |:pyfile|.
-
+The `:py3file` command works similar to `:pyfile`.
*:py3do* *E863*
-:[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}
+The `:py3do` command works similar to `:pydo`.
-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)
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
index b9ad364ff9..75e1724e5f 100644
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -739,6 +739,8 @@ EX(CMD_pwd, "pwd", ex_pwd,
TRLBAR|CMDWIN),
EX(CMD_python, "python", ex_python,
RANGE|EXTRA|NEEDARG|CMDWIN),
+EX(CMD_pydo, "pydo", ex_pydo,
+ RANGE|DFLALL|EXTRA|NEEDARG|CMDWIN),
EX(CMD_pyfile, "pyfile", ex_pyfile,
RANGE|FILE1|NEEDARG|CMDWIN),
EX(CMD_py3, "py3", ex_py3,
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 5ce0b5d97f..056339e7ea 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -268,6 +268,7 @@ static void ex_popup __ARGS((exarg_T *eap));
#endif
#ifndef FEAT_PYTHON
# define ex_python ex_script_ni
+# define ex_pydo ex_ni
# define ex_pyfile ex_ni
#endif
#ifndef FEAT_PYTHON3
diff --git a/src/if_py_both.h b/src/if_py_both.h
index c25be53e9b..280c248412 100644
--- a/src/if_py_both.h
+++ b/src/if_py_both.h
@@ -22,6 +22,7 @@ typedef int Py_ssize_t; /* Python 2.4 and earlier don't have this type. */
#else
# define ENC_OPT "latin1"
#endif
+#define DOPY_FUNC "_vim_pydo"
#define PyErr_SetVim(str) PyErr_SetString(VimError, str)
diff --git a/src/if_python.c b/src/if_python.c
index baa8cab878..5874103f0f 100644
--- 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)(PyObject *);
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().
*/
diff --git a/src/if_python3.c b/src/if_python3.c
index 7ceb13d932..0aeb2cd00a 100644
--- a/src/if_python3.c
+++ b/src/if_python3.c
@@ -76,7 +76,6 @@ 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
diff --git a/src/proto/if_python.pro b/src/proto/if_python.pro
index 4ba977cfb8..8aa7674638 100644
--- a/src/proto/if_python.pro
+++ b/src/proto/if_python.pro
@@ -3,6 +3,7 @@ int python_enabled __ARGS((int verbose));
void python_end __ARGS((void));
int python_loaded __ARGS((void));
void ex_python __ARGS((exarg_T *eap));
+void ex_pydo __ARGS((exarg_T *eap));
void ex_pyfile __ARGS((exarg_T *eap));
void python_buffer_free __ARGS((buf_T *buf));
void python_window_free __ARGS((win_T *win));
diff --git a/src/version.c b/src/version.c
index b76e9c4427..97611e487a 100644
--- 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 */
/**/
+ 966,
+/**/
965,
/**/
964,