forked from aniani/vim
updated for version 7.3.957
Problem: Python does not have a "do" command like Perl or Lua. Solution: Add the ":py3do" command. (Lilydjwg)
This commit is contained in:
@@ -490,6 +490,21 @@ if the `:py3` command is working: >
|
|||||||
< *:py3file*
|
< *:py3file*
|
||||||
The |:py3file| command works similar to |:pyfile|.
|
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):
|
Vim can be built in four ways (:version output):
|
||||||
1. No Python support (-python, -python3)
|
1. No Python support (-python, -python3)
|
||||||
|
@@ -743,6 +743,8 @@ EX(CMD_pyfile, "pyfile", ex_pyfile,
|
|||||||
RANGE|FILE1|NEEDARG|CMDWIN),
|
RANGE|FILE1|NEEDARG|CMDWIN),
|
||||||
EX(CMD_py3, "py3", ex_py3,
|
EX(CMD_py3, "py3", ex_py3,
|
||||||
RANGE|EXTRA|NEEDARG|CMDWIN),
|
RANGE|EXTRA|NEEDARG|CMDWIN),
|
||||||
|
EX(CMD_py3do, "py3do", ex_py3do,
|
||||||
|
RANGE|DFLALL|EXTRA|NEEDARG|CMDWIN),
|
||||||
EX(CMD_python3, "python3", ex_py3,
|
EX(CMD_python3, "python3", ex_py3,
|
||||||
RANGE|EXTRA|NEEDARG|CMDWIN),
|
RANGE|EXTRA|NEEDARG|CMDWIN),
|
||||||
EX(CMD_py3file, "py3file", ex_py3file,
|
EX(CMD_py3file, "py3file", ex_py3file,
|
||||||
|
@@ -272,6 +272,7 @@ static void ex_popup __ARGS((exarg_T *eap));
|
|||||||
#endif
|
#endif
|
||||||
#ifndef FEAT_PYTHON3
|
#ifndef FEAT_PYTHON3
|
||||||
# define ex_py3 ex_script_ni
|
# define ex_py3 ex_script_ni
|
||||||
|
# define ex_py3do ex_ni
|
||||||
# define ex_py3file ex_ni
|
# define ex_py3file ex_ni
|
||||||
#endif
|
#endif
|
||||||
#ifndef FEAT_TCL
|
#ifndef FEAT_TCL
|
||||||
|
113
src/if_python3.c
113
src/if_python3.c
@@ -76,6 +76,7 @@ static void init_structs(void);
|
|||||||
#else
|
#else
|
||||||
# define CODEC_ERROR_HANDLER NULL
|
# define CODEC_ERROR_HANDLER NULL
|
||||||
#endif
|
#endif
|
||||||
|
#define DOPY_FUNC "_vim_pydo"
|
||||||
|
|
||||||
/* Python 3 does not support CObjects, always use Capsules */
|
/* Python 3 does not support CObjects, always use Capsules */
|
||||||
#define PY_USE_CAPSULE
|
#define PY_USE_CAPSULE
|
||||||
@@ -126,6 +127,7 @@ static void init_structs(void);
|
|||||||
# define PyErr_PrintEx py3_PyErr_PrintEx
|
# define PyErr_PrintEx py3_PyErr_PrintEx
|
||||||
# define PyErr_NoMemory py3_PyErr_NoMemory
|
# define PyErr_NoMemory py3_PyErr_NoMemory
|
||||||
# define PyErr_Occurred py3_PyErr_Occurred
|
# define PyErr_Occurred py3_PyErr_Occurred
|
||||||
|
# define PyErr_PrintEx py3_PyErr_PrintEx
|
||||||
# define PyErr_SetNone py3_PyErr_SetNone
|
# define PyErr_SetNone py3_PyErr_SetNone
|
||||||
# define PyErr_SetString py3_PyErr_SetString
|
# define PyErr_SetString py3_PyErr_SetString
|
||||||
# define PyErr_SetObject py3_PyErr_SetObject
|
# define PyErr_SetObject py3_PyErr_SetObject
|
||||||
@@ -148,7 +150,6 @@ static void init_structs(void);
|
|||||||
# define PyTuple_GetItem py3_PyTuple_GetItem
|
# define PyTuple_GetItem py3_PyTuple_GetItem
|
||||||
# define PySlice_GetIndicesEx py3_PySlice_GetIndicesEx
|
# define PySlice_GetIndicesEx py3_PySlice_GetIndicesEx
|
||||||
# define PyImport_ImportModule py3_PyImport_ImportModule
|
# define PyImport_ImportModule py3_PyImport_ImportModule
|
||||||
# define PyImport_AddModule py3_PyImport_AddModule
|
|
||||||
# define PyObject_Init py3__PyObject_Init
|
# define PyObject_Init py3__PyObject_Init
|
||||||
# define PyDict_New py3_PyDict_New
|
# define PyDict_New py3_PyDict_New
|
||||||
# define PyDict_GetItemString py3_PyDict_GetItemString
|
# define PyDict_GetItemString py3_PyDict_GetItemString
|
||||||
@@ -163,6 +164,11 @@ static void init_structs(void);
|
|||||||
# define PyRun_SimpleString py3_PyRun_SimpleString
|
# define PyRun_SimpleString py3_PyRun_SimpleString
|
||||||
#undef PyRun_String
|
#undef PyRun_String
|
||||||
# define PyRun_String py3_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_SetObject py3_PySys_SetObject
|
||||||
# define PySys_SetArgv py3_PySys_SetArgv
|
# define PySys_SetArgv py3_PySys_SetArgv
|
||||||
# define PyType_Ready py3_PyType_Ready
|
# define PyType_Ready py3_PyType_Ready
|
||||||
@@ -178,6 +184,7 @@ static void init_structs(void);
|
|||||||
# define _PyObject_NextNotImplemented (*py3__PyObject_NextNotImplemented)
|
# define _PyObject_NextNotImplemented (*py3__PyObject_NextNotImplemented)
|
||||||
# define PyModule_AddObject py3_PyModule_AddObject
|
# define PyModule_AddObject py3_PyModule_AddObject
|
||||||
# define PyImport_AppendInittab py3_PyImport_AppendInittab
|
# define PyImport_AppendInittab py3_PyImport_AppendInittab
|
||||||
|
# define PyImport_AddModule py3_PyImport_AddModule
|
||||||
# if PY_VERSION_HEX >= 0x030300f0
|
# if PY_VERSION_HEX >= 0x030300f0
|
||||||
# undef _PyUnicode_AsString
|
# undef _PyUnicode_AsString
|
||||||
# define _PyUnicode_AsString py3_PyUnicode_AsUTF8
|
# define _PyUnicode_AsString py3_PyUnicode_AsUTF8
|
||||||
@@ -254,6 +261,11 @@ static void (*py3_PyErr_SetString)(PyObject *, const char *);
|
|||||||
static void (*py3_PyErr_SetObject)(PyObject *, PyObject *);
|
static void (*py3_PyErr_SetObject)(PyObject *, PyObject *);
|
||||||
static int (*py3_PyRun_SimpleString)(char *);
|
static int (*py3_PyRun_SimpleString)(char *);
|
||||||
static PyObject* (*py3_PyRun_String)(char *, int, PyObject *, PyObject *);
|
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_PyList_GetItem)(PyObject *, Py_ssize_t);
|
||||||
static PyObject* (*py3_PyImport_ImportModule)(const char *);
|
static PyObject* (*py3_PyImport_ImportModule)(const char *);
|
||||||
static PyObject* (*py3_PyImport_AddModule)(const char *);
|
static PyObject* (*py3_PyImport_AddModule)(const char *);
|
||||||
@@ -386,6 +398,11 @@ static struct
|
|||||||
{"PyErr_SetObject", (PYTHON_PROC*)&py3_PyErr_SetObject},
|
{"PyErr_SetObject", (PYTHON_PROC*)&py3_PyErr_SetObject},
|
||||||
{"PyRun_SimpleString", (PYTHON_PROC*)&py3_PyRun_SimpleString},
|
{"PyRun_SimpleString", (PYTHON_PROC*)&py3_PyRun_SimpleString},
|
||||||
{"PyRun_String", (PYTHON_PROC*)&py3_PyRun_String},
|
{"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},
|
{"PyList_GetItem", (PYTHON_PROC*)&py3_PyList_GetItem},
|
||||||
{"PyImport_ImportModule", (PYTHON_PROC*)&py3_PyImport_ImportModule},
|
{"PyImport_ImportModule", (PYTHON_PROC*)&py3_PyImport_ImportModule},
|
||||||
{"PyImport_AddModule", (PYTHON_PROC*)&py3_PyImport_AddModule},
|
{"PyImport_AddModule", (PYTHON_PROC*)&py3_PyImport_AddModule},
|
||||||
@@ -990,6 +1007,100 @@ ex_py3file(exarg_T *eap)
|
|||||||
DoPy3Command(eap, buffer, NULL);
|
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().
|
* 2. Python output stream: writes output via [e]msg().
|
||||||
*/
|
*/
|
||||||
|
@@ -3,6 +3,7 @@ int python3_enabled __ARGS((int verbose));
|
|||||||
void python3_end __ARGS((void));
|
void python3_end __ARGS((void));
|
||||||
int python3_loaded __ARGS((void));
|
int python3_loaded __ARGS((void));
|
||||||
void ex_py3 __ARGS((exarg_T *eap));
|
void ex_py3 __ARGS((exarg_T *eap));
|
||||||
|
void ex_py3do __ARGS((exarg_T *eap));
|
||||||
void ex_py3file __ARGS((exarg_T *eap));
|
void ex_py3file __ARGS((exarg_T *eap));
|
||||||
void python3_buffer_free __ARGS((buf_T *buf));
|
void python3_buffer_free __ARGS((buf_T *buf));
|
||||||
void python3_window_free __ARGS((win_T *win));
|
void python3_window_free __ARGS((win_T *win));
|
||||||
|
@@ -728,6 +728,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
957,
|
||||||
/**/
|
/**/
|
||||||
956,
|
956,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user