Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

updated for version 7.3.569

Problem:    Evaluating Vim expression in Python is insufficient.
Solution:   Add vim.bindeval().  Also add pyeval() and py3eval(). (ZyX)
  • Loading branch information...
commit 92591ff7987fd78e0af8a2d583d8e651e97f3aaa 1 parent f9ba7b5
Bram Moolenaar authored
View
153 src/eval.c
@@ -424,30 +424,21 @@ static int get_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
static int get_lit_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
static int get_list_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
static int rettv_list_alloc __ARGS((typval_T *rettv));
-static listitem_T *listitem_alloc __ARGS((void));
static void listitem_free __ARGS((listitem_T *item));
-static void listitem_remove __ARGS((list_T *l, listitem_T *item));
static long list_len __ARGS((list_T *l));
static int list_equal __ARGS((list_T *l1, list_T *l2, int ic, int recursive));
static int dict_equal __ARGS((dict_T *d1, dict_T *d2, int ic, int recursive));
static int tv_equal __ARGS((typval_T *tv1, typval_T *tv2, int ic, int recursive));
-static listitem_T *list_find __ARGS((list_T *l, long n));
static long list_find_nr __ARGS((list_T *l, long idx, int *errorp));
static long list_idx_of_item __ARGS((list_T *l, listitem_T *item));
-static void list_append __ARGS((list_T *l, listitem_T *item));
static int list_append_number __ARGS((list_T *l, varnumber_T n));
-static int list_insert_tv __ARGS((list_T *l, typval_T *tv, listitem_T *item));
static int list_extend __ARGS((list_T *l1, list_T *l2, listitem_T *bef));
static int list_concat __ARGS((list_T *l1, list_T *l2, typval_T *tv));
static list_T *list_copy __ARGS((list_T *orig, int deep, int copyID));
-static void list_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2));
static char_u *list2string __ARGS((typval_T *tv, int copyID));
static int list_join_inner __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo_style, int copyID, garray_T *join_gap));
static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo, int copyID));
static int free_unref_items __ARGS((int copyID));
-static void set_ref_in_ht __ARGS((hashtab_T *ht, int copyID));
-static void set_ref_in_list __ARGS((list_T *l, int copyID));
-static void set_ref_in_item __ARGS((typval_T *tv, int copyID));
static int rettv_dict_alloc __ARGS((typval_T *rettv));
static void dict_free __ARGS((dict_T *d, int recurse));
static dictitem_T *dictitem_copy __ARGS((dictitem_T *org));
@@ -654,6 +645,12 @@ static void f_pow __ARGS((typval_T *argvars, typval_T *rettv));
static void f_prevnonblank __ARGS((typval_T *argvars, typval_T *rettv));
static void f_printf __ARGS((typval_T *argvars, typval_T *rettv));
static void f_pumvisible __ARGS((typval_T *argvars, typval_T *rettv));
+#ifdef FEAT_PYTHON3
+static void f_py3eval __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
+#ifdef FEAT_PYTHON
+static void f_pyeval __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
static void f_range __ARGS((typval_T *argvars, typval_T *rettv));
static void f_readfile __ARGS((typval_T *argvars, typval_T *rettv));
static void f_reltime __ARGS((typval_T *argvars, typval_T *rettv));
@@ -824,8 +821,6 @@ static int script_autoload __ARGS((char_u *name, int reload));
static char_u *autoload_name __ARGS((char_u *name));
static void cat_func_name __ARGS((char_u *buf, ufunc_T *fp));
static void func_free __ARGS((ufunc_T *fp));
-static void func_unref __ARGS((char_u *name));
-static void func_ref __ARGS((char_u *name));
static void call_user_func __ARGS((ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, linenr_T firstline, linenr_T lastline, dict_T *selfdict));
static int can_free_funccal __ARGS((funccall_T *fc, int copyID)) ;
static void free_funccal __ARGS((funccall_T *fc, int free_val));
@@ -5927,7 +5922,7 @@ list_free(l, recurse)
/*
* Allocate a list item.
*/
- static listitem_T *
+ listitem_T *
listitem_alloc()
{
return (listitem_T *)alloc(sizeof(listitem_T));
@@ -5947,7 +5942,7 @@ listitem_free(item)
/*
* Remove a list item from a List and free it. Also clears the value.
*/
- static void
+ void
listitem_remove(l, item)
list_T *l;
listitem_T *item;
@@ -6123,7 +6118,7 @@ tv_equal(tv1, tv2, ic, recursive)
* A negative index is counted from the end; -1 is the last item.
* Returns NULL when "n" is out of range.
*/
- static listitem_T *
+ listitem_T *
list_find(l, n)
list_T *l;
long n;
@@ -6265,7 +6260,7 @@ list_idx_of_item(l, item)
/*
* Append item "item" to the end of list "l".
*/
- static void
+ void
list_append(l, item)
list_T *l;
listitem_T *item;
@@ -6378,7 +6373,7 @@ list_append_number(l, n)
* If "item" is NULL append at the end.
* Return FAIL when out of memory.
*/
- static int
+ int
list_insert_tv(l, tv, item)
list_T *l;
typval_T *tv;
@@ -6523,7 +6518,7 @@ list_copy(orig, deep, copyID)
* Remove items "item" to "item2" from list "l".
* Does not free the listitem or the value!
*/
- static void
+ void
list_remove(l, item, item2)
list_T *l;
listitem_T *item;
@@ -6785,6 +6780,14 @@ garbage_collect()
set_ref_in_lua(copyID);
#endif
+#ifdef FEAT_PYTHON
+ set_ref_in_python(copyID);
+#endif
+
+#ifdef FEAT_PYTHON3
+ set_ref_in_python3(copyID);
+#endif
+
/*
* 2. Free lists and dictionaries that are not referenced.
*/
@@ -6870,7 +6873,7 @@ free_unref_items(copyID)
/*
* Mark all lists and dicts referenced through hashtab "ht" with "copyID".
*/
- static void
+ void
set_ref_in_ht(ht, copyID)
hashtab_T *ht;
int copyID;
@@ -6890,7 +6893,7 @@ set_ref_in_ht(ht, copyID)
/*
* Mark all lists and dicts referenced through list "l" with "copyID".
*/
- static void
+ void
set_ref_in_list(l, copyID)
list_T *l;
int copyID;
@@ -6904,7 +6907,7 @@ set_ref_in_list(l, copyID)
/*
* Mark all lists and dicts referenced through typval "tv" with "copyID".
*/
- static void
+ void
set_ref_in_item(tv, copyID)
typval_T *tv;
int copyID;
@@ -7986,6 +7989,12 @@ static struct fst
{"prevnonblank", 1, 1, f_prevnonblank},
{"printf", 2, 19, f_printf},
{"pumvisible", 0, 0, f_pumvisible},
+#ifdef FEAT_PYTHON3
+ {"py3eval", 1, 1, f_py3eval},
+#endif
+#ifdef FEAT_PYTHON
+ {"pyeval", 1, 1, f_pyeval},
+#endif
{"range", 1, 3, f_range},
{"readfile", 1, 3, f_readfile},
{"reltime", 0, 2, f_reltime},
@@ -9150,6 +9159,45 @@ f_byteidx(argvars, rettv)
#endif
}
+ int
+func_call(name, args, selfdict, rettv)
+ char_u *name;
+ typval_T *args;
+ dict_T *selfdict;
+ typval_T *rettv;
+{
+ listitem_T *item;
+ typval_T argv[MAX_FUNC_ARGS + 1];
+ int argc = 0;
+ int dummy;
+ int r = 0;
+
+ for (item = args->vval.v_list->lv_first; item != NULL;
+ item = item->li_next)
+ {
+ if (argc == MAX_FUNC_ARGS)
+ {
+ EMSG(_("E699: Too many arguments"));
+ break;
+ }
+ /* Make a copy of each argument. This is needed to be able to set
+ * v_lock to VAR_FIXED in the copy without changing the original list.
+ */
+ copy_tv(&item->li_tv, &argv[argc++]);
+ }
+
+ if (item == NULL)
+ r = call_func(name, (int)STRLEN(name), rettv, argc, argv,
+ curwin->w_cursor.lnum, curwin->w_cursor.lnum,
+ &dummy, TRUE, selfdict);
+
+ /* Free the arguments. */
+ while (argc > 0)
+ clear_tv(&argv[--argc]);
+
+ return r;
+}
+
/*
* "call(func, arglist)" function
*/
@@ -9159,10 +9207,6 @@ f_call(argvars, rettv)
typval_T *rettv;
{
char_u *func;
- typval_T argv[MAX_FUNC_ARGS + 1];
- int argc = 0;
- listitem_T *item;
- int dummy;
dict_T *selfdict = NULL;
if (argvars[1].v_type != VAR_LIST)
@@ -9190,28 +9234,7 @@ f_call(argvars, rettv)
selfdict = argvars[2].vval.v_dict;
}
- for (item = argvars[1].vval.v_list->lv_first; item != NULL;
- item = item->li_next)
- {
- if (argc == MAX_FUNC_ARGS)
- {
- EMSG(_("E699: Too many arguments"));
- break;
- }
- /* Make a copy of each argument. This is needed to be able to set
- * v_lock to VAR_FIXED in the copy without changing the original list.
- */
- copy_tv(&item->li_tv, &argv[argc++]);
- }
-
- if (item == NULL)
- (void)call_func(func, (int)STRLEN(func), rettv, argc, argv,
- curwin->w_cursor.lnum, curwin->w_cursor.lnum,
- &dummy, TRUE, selfdict);
-
- /* Free the arguments. */
- while (argc > 0)
- clear_tv(&argv[--argc]);
+ (void)func_call(func, &argvars[1], selfdict, rettv);
}
#ifdef FEAT_FLOAT
@@ -14424,6 +14447,40 @@ f_pumvisible(argvars, rettv)
#endif
}
+#ifdef FEAT_PYTHON3
+/*
+ * "py3eval()" function
+ */
+ static void
+f_py3eval(argvars, rettv)
+ typval_T *argvars;
+ typval_T *rettv;
+{
+ char_u *str;
+ char_u buf[NUMBUFLEN];
+
+ str = get_tv_string_buf(&argvars[0], buf);
+ do_py3eval(str, rettv);
+}
+#endif
+
+#ifdef FEAT_PYTHON
+/*
+ * "pyeval()" function
+ */
+ static void
+f_pyeval(argvars, rettv)
+ typval_T *argvars;
+ typval_T *rettv;
+{
+ char_u *str;
+ char_u buf[NUMBUFLEN];
+
+ str = get_tv_string_buf(&argvars[0], buf);
+ do_pyeval(str, rettv);
+}
+#endif
+
/*
* "range()" function
*/
@@ -22139,7 +22196,7 @@ func_free(fp)
* Unreference a Function: decrement the reference count and free it when it
* becomes zero. Only for numbered functions.
*/
- static void
+ void
func_unref(name)
char_u *name;
{
@@ -22163,7 +22220,7 @@ func_unref(name)
/*
* Count a reference to a Function.
*/
- static void
+ void
func_ref(name)
char_u *name;
{
View
148 src/if_lua.c
@@ -199,9 +199,9 @@ int (*dll_lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
lua_Number (*dll_lua_tonumberx) (lua_State *L, int idx, int *isnum);
lua_Integer (*dll_lua_tointegerx) (lua_State *L, int idx, int *isnum);
void (*dll_lua_callk) (lua_State *L, int nargs, int nresults, int ctx,
- lua_CFunction k);
+ lua_CFunction k);
int (*dll_lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc,
- int ctx, lua_CFunction k);
+ int ctx, lua_CFunction k);
void (*dll_lua_getglobal) (lua_State *L, const char *var);
void (*dll_lua_setglobal) (lua_State *L, const char *var);
#endif
@@ -394,7 +394,7 @@ lua_enabled(int verbose)
luaL_typeerror (lua_State *L, int narg, const char *tname)
{
const char *msg = lua_pushfstring(L, "%s expected, got %s",
- tname, luaL_typename(L, narg));
+ tname, luaL_typename(L, narg));
return luaL_argerror(L, narg, msg);
}
#endif
@@ -646,141 +646,6 @@ luaV_msgfunc(lua_State *L, msgfunc_T mf)
return 1; \
}
-
-/* adapted from eval.c */
-
-#define listitem_alloc() (listitem_T *)alloc(sizeof(listitem_T))
-
- static listitem_T *
-list_find (list_T *l, long n)
-{
- listitem_T *li;
- if (l == NULL || n < -l->lv_len || n >= l->lv_len)
- return NULL;
- if (n < 0) /* search backward? */
- for (li = l->lv_last; n < -1; li = li->li_prev)
- n++;
- else /* search forward */
- for (li = l->lv_first; n > 0; li = li->li_next)
- n--;
- return li;
-}
-
- static void
-list_remove (list_T *l, listitem_T *li)
-{
- listwatch_T *lw;
- --l->lv_len;
- /* fix watchers */
- for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
- if (lw->lw_item == li)
- lw->lw_item = li->li_next;
- /* fix list pointers */
- if (li->li_next == NULL) /* last? */
- l->lv_last = li->li_prev;
- else
- li->li_next->li_prev = li->li_prev;
- if (li->li_prev == NULL) /* first? */
- l->lv_first = li->li_next;
- else
- li->li_prev->li_next = li->li_next;
- l->lv_idx_item = NULL;
-}
-
- static void
-list_append(list_T *l, listitem_T *item)
-{
- if (l->lv_last == NULL) /* empty list? */
- l->lv_first = item;
- else
- l->lv_last->li_next = item;
- item->li_prev = l->lv_last;
- item->li_next = NULL;
- l->lv_last = item;
- ++l->lv_len;
-}
-
- static int
-list_insert_tv(list_T *l, typval_T *tv, listitem_T *item)
-{
- listitem_T *ni = listitem_alloc();
-
- if (ni == NULL)
- return FAIL;
- copy_tv(tv, &ni->li_tv);
- if (item == NULL)
- list_append(l, ni);
- else
- {
- ni->li_prev = item->li_prev;
- ni->li_next = item;
- if (item->li_prev == NULL)
- {
- l->lv_first = ni;
- ++l->lv_idx;
- }
- else
- {
- item->li_prev->li_next = ni;
- l->lv_idx_item = NULL;
- }
- item->li_prev = ni;
- ++l->lv_len;
- }
- return OK;
-}
-
-/* set references */
-
-static void set_ref_in_tv (typval_T *tv, int copyID);
-
- static void
-set_ref_in_dict(dict_T *d, int copyID)
-{
- hashtab_T *ht = &d->dv_hashtab;
- int n = ht->ht_used;
- hashitem_T *hi;
- for (hi = ht->ht_array; n > 0; ++hi)
- if (!HASHITEM_EMPTY(hi))
- {
- dictitem_T *di = dict_lookup(hi);
- set_ref_in_tv(&di->di_tv, copyID);
- --n;
- }
-}
-
- static void
-set_ref_in_list(list_T *l, int copyID)
-{
- listitem_T *li;
- for (li = l->lv_first; li != NULL; li = li->li_next)
- set_ref_in_tv(&li->li_tv, copyID);
-}
-
- static void
-set_ref_in_tv(typval_T *tv, int copyID)
-{
- if (tv->v_type == VAR_LIST)
- {
- list_T *l = tv->vval.v_list;
- if (l != NULL && l->lv_copyID != copyID)
- {
- l->lv_copyID = copyID;
- set_ref_in_list(l, copyID);
- }
- }
- else if (tv->v_type == VAR_DICT)
- {
- dict_T *d = tv->vval.v_dict;
- if (d != NULL && d->dv_copyID != copyID)
- {
- d->dv_copyID = copyID;
- set_ref_in_dict(d, copyID);
- }
- }
-}
-
-
/* ======= List type ======= */
static luaV_List *
@@ -876,7 +741,7 @@ luaV_list_newindex (lua_State *L)
if (li == NULL) return 0;
if (lua_isnil(L, 3)) /* remove? */
{
- list_remove(l, li);
+ list_remove(l, li, li);
clear_tv(&li->li_tv);
vim_free(li);
}
@@ -904,8 +769,7 @@ luaV_list_add (lua_State *L)
typval_T v;
lua_settop(L, 2);
luaV_totypval(L, 2, &v);
- copy_tv(&v, &li->li_tv);
- list_append(l, li);
+ list_append_tv(l, &v);
}
lua_settop(L, 1);
return 1;
@@ -1682,7 +1546,7 @@ luaV_setref (lua_State *L)
tv.vval.v_dict = (dict_T *) lua_touserdata(L, 4); /* key */
}
lua_pop(L, 2); /* metatable and value */
- set_ref_in_tv(&tv, copyID);
+ set_ref_in_item(&tv, copyID);
}
return 0;
}
View
1,253 src/if_py_both.h
@@ -1,4 +1,4 @@
-/* vi:set ts=8 sts=4 sw=4:
+/* vi:set ts=8 sts=4 sw=4 noet:
*
* VIM - Vi IMproved by Bram Moolenaar
*
@@ -105,7 +105,8 @@ OutputWritelines(PyObject *self, PyObject *args)
return NULL;
Py_INCREF(list);
- if (!PyList_Check(list)) {
+ if (!PyList_Check(list))
+ {
PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings"));
Py_DECREF(list);
return NULL;
@@ -119,7 +120,8 @@ OutputWritelines(PyObject *self, PyObject *args)
char *str = NULL;
PyInt len;
- if (!PyArg_Parse(line, "et#", ENC_OPT, &str, &len)) {
+ if (!PyArg_Parse(line, "et#", ENC_OPT, &str, &len))
+ {
PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings"));
Py_DECREF(list);
return NULL;
@@ -297,7 +299,7 @@ VimToPython(typval_T *our_tv, int depth, PyObject *lookupDict)
{
PyObject *result;
PyObject *newObj;
- char ptrBuf[NUMBUFLEN];
+ char ptrBuf[sizeof(void *) * 2 + 3];
/* Avoid infinite recursion */
if (depth > 100)
@@ -312,9 +314,9 @@ VimToPython(typval_T *our_tv, int depth, PyObject *lookupDict)
if ((our_tv->v_type == VAR_LIST && our_tv->vval.v_list != NULL)
|| (our_tv->v_type == VAR_DICT && our_tv->vval.v_dict != NULL))
{
- sprintf(ptrBuf, PRINTF_DECIMAL_LONG_U,
- our_tv->v_type == VAR_LIST ? (long_u)our_tv->vval.v_list
- : (long_u)our_tv->vval.v_dict);
+ sprintf(ptrBuf, "%p",
+ our_tv->v_type == VAR_LIST ? (void *)our_tv->vval.v_list
+ : (void *)our_tv->vval.v_dict);
result = PyDict_GetItemString(lookupDict, ptrBuf);
if (result != NULL)
{
@@ -374,136 +376,950 @@ VimToPython(typval_T *our_tv, int depth, PyObject *lookupDict)
hashitem_T *hi;
dictitem_T *di;
- PyDict_SetItemString(lookupDict, ptrBuf, result);
+ PyDict_SetItemString(lookupDict, ptrBuf, result);
+
+ for (hi = ht->ht_array; todo > 0; ++hi)
+ {
+ if (!HASHITEM_EMPTY(hi))
+ {
+ --todo;
+
+ di = dict_lookup(hi);
+ newObj = VimToPython(&di->di_tv, depth + 1, lookupDict);
+ PyDict_SetItemString(result, (char *)hi->hi_key, newObj);
+ Py_DECREF(newObj);
+ }
+ }
+ }
+ }
+ else
+ {
+ Py_INCREF(Py_None);
+ result = Py_None;
+ }
+
+ return result;
+}
+#endif
+
+ static PyObject *
+VimEval(PyObject *self UNUSED, PyObject *args UNUSED)
+{
+#ifdef FEAT_EVAL
+ char *expr;
+ typval_T *our_tv;
+ PyObject *result;
+ PyObject *lookup_dict;
+
+ if (!PyArg_ParseTuple(args, "s", &expr))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ Python_Lock_Vim();
+ our_tv = eval_expr((char_u *)expr, NULL);
+
+ Python_Release_Vim();
+ Py_END_ALLOW_THREADS
+
+ if (our_tv == NULL)
+ {
+ PyErr_SetVim(_("invalid expression"));
+ return NULL;
+ }
+
+ /* Convert the Vim type into a Python type. Create a dictionary that's
+ * used to check for recursive loops. */
+ lookup_dict = PyDict_New();
+ result = VimToPython(our_tv, 1, lookup_dict);
+ Py_DECREF(lookup_dict);
+
+
+ Py_BEGIN_ALLOW_THREADS
+ Python_Lock_Vim();
+ free_tv(our_tv);
+ Python_Release_Vim();
+ Py_END_ALLOW_THREADS
+
+ return result;
+#else
+ PyErr_SetVim(_("expressions disabled at compile time"));
+ return NULL;
+#endif
+}
+
+static PyObject *ConvertToPyObject(typval_T *);
+
+ static PyObject *
+VimEvalPy(PyObject *self UNUSED, PyObject *args UNUSED)
+{
+#ifdef FEAT_EVAL
+ char *expr;
+ typval_T *our_tv;
+ PyObject *result;
+
+ if (!PyArg_ParseTuple(args, "s", &expr))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ Python_Lock_Vim();
+ our_tv = eval_expr((char_u *)expr, NULL);
+
+ Python_Release_Vim();
+ Py_END_ALLOW_THREADS
+
+ if (our_tv == NULL)
+ {
+ PyErr_SetVim(_("invalid expression"));
+ return NULL;
+ }
+
+ result = ConvertToPyObject(our_tv);
+ Py_BEGIN_ALLOW_THREADS
+ Python_Lock_Vim();
+ free_tv(our_tv);
+ Python_Release_Vim();
+ Py_END_ALLOW_THREADS
+
+ return result;
+#else
+ PyErr_SetVim(_("expressions disabled at compile time"));
+ return NULL;
+#endif
+}
+
+ static PyObject *
+VimStrwidth(PyObject *self UNUSED, PyObject *args)
+{
+ char *expr;
+
+ if (!PyArg_ParseTuple(args, "s", &expr))
+ return NULL;
+
+ return PyLong_FromLong(mb_string2cells((char_u *)expr, STRLEN(expr)));
+}
+
+/*
+ * Vim module - Definitions
+ */
+
+static struct PyMethodDef VimMethods[] = {
+ /* name, function, calling, documentation */
+ {"command", VimCommand, 1, "Execute a Vim ex-mode command" },
+ {"eval", VimEval, 1, "Evaluate an expression using Vim evaluator" },
+ {"bindeval", VimEvalPy, 1, "Like eval(), but returns objects attached to vim ones"},
+ {"strwidth", VimStrwidth, 1, "Screen string width, counts <Tab> as having width 1"},
+ { NULL, NULL, 0, NULL }
+};
+
+typedef struct
+{
+ PyObject_HEAD
+ buf_T *buf;
+} BufferObject;
+
+#define INVALID_BUFFER_VALUE ((buf_T *)(-1))
+
+/*
+ * Buffer list object - Implementation
+ */
+
+ static PyInt
+BufListLength(PyObject *self UNUSED)
+{
+ buf_T *b = firstbuf;
+ PyInt n = 0;
+
+ while (b)
+ {
+ ++n;
+ b = b->b_next;
+ }
+
+ return n;
+}
+
+ static PyObject *
+BufListItem(PyObject *self UNUSED, PyInt n)
+{
+ buf_T *b;
+
+ for (b = firstbuf; b; b = b->b_next, --n)
+ {
+ if (n == 0)
+ return BufferNew(b);
+ }
+
+ PyErr_SetString(PyExc_IndexError, _("no such buffer"));
+ return NULL;
+}
+
+typedef struct
+{
+ PyObject_HEAD
+ win_T *win;
+} WindowObject;
+
+static int ConvertFromPyObject(PyObject *, typval_T *);
+static int _ConvertFromPyObject(PyObject *, typval_T *, PyObject *);
+
+typedef struct pylinkedlist_S {
+ struct pylinkedlist_S *pll_next;
+ struct pylinkedlist_S *pll_prev;
+ PyObject *pll_obj;
+} pylinkedlist_T;
+
+static pylinkedlist_T *lastdict = NULL;
+static pylinkedlist_T *lastlist = NULL;
+
+ static void
+pyll_remove(pylinkedlist_T *ref, pylinkedlist_T **last)
+{
+ if (ref->pll_prev == NULL)
+ {
+ if (ref->pll_next == NULL)
+ {
+ *last = NULL;
+ return;
+ }
+ }
+ else
+ ref->pll_prev->pll_next = ref->pll_next;
+
+ if (ref->pll_next == NULL)
+ *last = ref->pll_prev;
+ else
+ ref->pll_next->pll_prev = ref->pll_prev;
+}
+
+ static void
+pyll_add(PyObject *self, pylinkedlist_T *ref, pylinkedlist_T **last)
+{
+ if (*last == NULL)
+ ref->pll_prev = NULL;
+ else
+ {
+ (*last)->pll_next = ref;
+ ref->pll_prev = *last;
+ }
+ ref->pll_next = NULL;
+ ref->pll_obj = self;
+ *last = ref;
+}
+
+static PyTypeObject DictionaryType;
+
+typedef struct
+{
+ PyObject_HEAD
+ dict_T *dict;
+ pylinkedlist_T ref;
+} DictionaryObject;
+
+ static PyObject *
+DictionaryNew(dict_T *dict)
+{
+ DictionaryObject *self;
+
+ self = PyObject_NEW(DictionaryObject, &DictionaryType);
+ if (self == NULL)
+ return NULL;
+ self->dict = dict;
+ ++dict->dv_refcount;
+
+ pyll_add((PyObject *)(self), &self->ref, &lastdict);
+
+ return (PyObject *)(self);
+}
+
+ static int
+pydict_to_tv(PyObject *obj, typval_T *tv, PyObject *lookupDict)
+{
+ dict_T *d;
+ char_u *key;
+ dictitem_T *di;
+ PyObject *keyObject;
+ PyObject *valObject;
+ Py_ssize_t iter = 0;
+
+ d = dict_alloc();
+ if (d == NULL)
+ {
+ PyErr_NoMemory();
+ return -1;
+ }
+
+ tv->v_type = VAR_DICT;
+ tv->vval.v_dict = d;
+
+ while (PyDict_Next(obj, &iter, &keyObject, &valObject))
+ {
+ DICTKEY_DECL
+
+ if (keyObject == NULL)
+ return -1;
+ if (valObject == NULL)
+ return -1;
+
+ DICTKEY_GET(-1)
+
+ di = dictitem_alloc(key);
+
+ DICTKEY_UNREF
+
+ if (di == NULL)
+ {
+ PyErr_NoMemory();
+ return -1;
+ }
+ di->di_tv.v_lock = 0;
+
+ if (_ConvertFromPyObject(valObject, &di->di_tv, lookupDict) == -1)
+ {
+ vim_free(di);
+ return -1;
+ }
+ if (dict_add(d, di) == FAIL)
+ {
+ vim_free(di);
+ PyErr_SetVim(_("failed to add key to dictionary"));
+ return -1;
+ }
+ }
+ return 0;
+}
+
+ static int
+pymap_to_tv(PyObject *obj, typval_T *tv, PyObject *lookupDict)
+{
+ dict_T *d;
+ char_u *key;
+ dictitem_T *di;
+ PyObject *list;
+ PyObject *litem;
+ PyObject *keyObject;
+ PyObject *valObject;
+ Py_ssize_t lsize;
+
+ d = dict_alloc();
+ if (d == NULL)
+ {
+ PyErr_NoMemory();
+ return -1;
+ }
+
+ tv->v_type = VAR_DICT;
+ tv->vval.v_dict = d;
+
+ list = PyMapping_Items(obj);
+ lsize = PyList_Size(list);
+ while (lsize--)
+ {
+ DICTKEY_DECL
+
+ litem = PyList_GetItem(list, lsize);
+ if (litem == NULL)
+ {
+ Py_DECREF(list);
+ return -1;
+ }
+
+ keyObject = PyTuple_GetItem(litem, 0);
+ if (keyObject == NULL)
+ {
+ Py_DECREF(list);
+ Py_DECREF(litem);
+ return -1;
+ }
+
+ DICTKEY_GET(-1)
+
+ valObject = PyTuple_GetItem(litem, 1);
+ if (valObject == NULL)
+ {
+ Py_DECREF(list);
+ Py_DECREF(litem);
+ return -1;
+ }
+
+ di = dictitem_alloc(key);
+
+ DICTKEY_UNREF
+
+ if (di == NULL)
+ {
+ Py_DECREF(list);
+ Py_DECREF(litem);
+ PyErr_NoMemory();
+ return -1;
+ }
+ di->di_tv.v_lock = 0;
+
+ if (_ConvertFromPyObject(valObject, &di->di_tv, lookupDict) == -1)
+ {
+ vim_free(di);
+ Py_DECREF(list);
+ Py_DECREF(litem);
+ return -1;
+ }
+ if (dict_add(d, di) == FAIL)
+ {
+ vim_free(di);
+ Py_DECREF(list);
+ Py_DECREF(litem);
+ PyErr_SetVim(_("failed to add key to dictionary"));
+ return -1;
+ }
+ Py_DECREF(litem);
+ }
+ Py_DECREF(list);
+ return 0;
+}
+
+ static PyInt
+DictionaryLength(PyObject *self)
+{
+ return ((PyInt) ((((DictionaryObject *)(self))->dict->dv_hashtab.ht_used)));
+}
+
+ static PyObject *
+DictionaryItem(PyObject *self, PyObject *keyObject)
+{
+ char_u *key;
+ dictitem_T *val;
+ DICTKEY_DECL
+
+ DICTKEY_GET(NULL)
+
+ val = dict_find(((DictionaryObject *) (self))->dict, key, -1);
+
+ DICTKEY_UNREF
+
+ return ConvertToPyObject(&val->di_tv);
+}
+
+ static PyInt
+DictionaryAssItem(PyObject *self, PyObject *keyObject, PyObject *valObject)
+{
+ char_u *key;
+ typval_T tv;
+ dict_T *d = ((DictionaryObject *)(self))->dict;
+ dictitem_T *di;
+ DICTKEY_DECL
+
+ if (d->dv_lock)
+ {
+ PyErr_SetVim(_("dict is locked"));
+ return -1;
+ }
+
+ DICTKEY_GET(-1)
+
+ di = dict_find(d, key, -1);
+
+ if (valObject == NULL)
+ {
+ if (di == NULL)
+ {
+ PyErr_SetString(PyExc_IndexError, _("no such key in dictionary"));
+ return -1;
+ }
+ hashitem_T *hi = hash_find(&d->dv_hashtab, di->di_key);
+ hash_remove(&d->dv_hashtab, hi);
+ dictitem_free(di);
+ return 0;
+ }
+
+ if (ConvertFromPyObject(valObject, &tv) == -1)
+ {
+ return -1;
+ }
+
+ if (di == NULL)
+ {
+ di = dictitem_alloc(key);
+ if (di == NULL)
+ {
+ PyErr_NoMemory();
+ return -1;
+ }
+ di->di_tv.v_lock = 0;
+
+ if (dict_add(d, di) == FAIL)
+ {
+ vim_free(di);
+ PyErr_SetVim(_("failed to add key to dictionary"));
+ return -1;
+ }
+ }
+ else
+ clear_tv(&di->di_tv);
+
+ DICTKEY_UNREF
+
+ copy_tv(&tv, &di->di_tv);
+ return 0;
+}
+
+ static PyObject *
+DictionaryListKeys(PyObject *self)
+{
+ dict_T *dict = ((DictionaryObject *)(self))->dict;
+ long_u todo = dict->dv_hashtab.ht_used;
+ Py_ssize_t i = 0;
+ PyObject *r;
+ hashitem_T *hi;
+
+ r = PyList_New(todo);
+ for (hi = dict->dv_hashtab.ht_array; todo > 0; ++hi)
+ {
+ if (!HASHITEM_EMPTY(hi))
+ {
+ PyList_SetItem(r, i, PyBytes_FromString((char *)(hi->hi_key)));
+ --todo;
+ ++i;
+ }
+ }
+ return r;
+}
+
+static struct PyMethodDef DictionaryMethods[] = {
+ {"keys", (PyCFunction)DictionaryListKeys, METH_NOARGS, ""},
+ { NULL, NULL, 0, NULL }
+};
+
+static PyTypeObject ListType;
+
+typedef struct
+{
+ PyObject_HEAD
+ list_T *list;
+ pylinkedlist_T ref;
+} ListObject;
+
+ static PyObject *
+ListNew(list_T *list)
+{
+ ListObject *self;
+
+ self = PyObject_NEW(ListObject, &ListType);
+ if (self == NULL)
+ return NULL;
+ self->list = list;
+ ++list->lv_refcount;
+
+ pyll_add((PyObject *)(self), &self->ref, &lastlist);
+
+ return (PyObject *)(self);
+}
+
+ static int
+list_py_concat(list_T *l, PyObject *obj, PyObject *lookupDict)
+{
+ Py_ssize_t i;
+ Py_ssize_t lsize = PySequence_Size(obj);
+ PyObject *litem;
+ listitem_T *li;
+
+ for(i=0; i<lsize; i++)
+ {
+ li = listitem_alloc();
+ if (li == NULL)
+ {
+ PyErr_NoMemory();
+ return -1;
+ }
+ li->li_tv.v_lock = 0;
+
+ litem = PySequence_GetItem(obj, i);
+ if (litem == NULL)
+ return -1;
+ if (_ConvertFromPyObject(litem, &li->li_tv, lookupDict) == -1)
+ return -1;
+
+ list_append(l, li);
+ }
+ return 0;
+}
+
+ static int
+pyseq_to_tv(PyObject *obj, typval_T *tv, PyObject *lookupDict)
+{
+ list_T *l;
+
+ l = list_alloc();
+ if (l == NULL)
+ {
+ PyErr_NoMemory();
+ return -1;
+ }
+
+ tv->v_type = VAR_LIST;
+ tv->vval.v_list = l;
+
+ if (list_py_concat(l, obj, lookupDict) == -1)
+ return -1;
+
+ return 0;
+}
+
+ static int
+pyiter_to_tv(PyObject *obj, typval_T *tv, PyObject *lookupDict)
+{
+ PyObject *iterator = PyObject_GetIter(obj);
+ PyObject *item;
+ list_T *l;
+ listitem_T *li;
+
+ l = list_alloc();
+
+ if (l == NULL)
+ {
+ PyErr_NoMemory();
+ return -1;
+ }
+
+ tv->vval.v_list = l;
+ tv->v_type = VAR_LIST;
+
+
+ if (iterator == NULL)
+ return -1;
+
+ while ((item = PyIter_Next(obj)))
+ {
+ li = listitem_alloc();
+ if (li == NULL)
+ {
+ PyErr_NoMemory();
+ return -1;
+ }
+ li->li_tv.v_lock = 0;
+
+ if (_ConvertFromPyObject(item, &li->li_tv, lookupDict) == -1)
+ return -1;
+
+ list_append(l, li);
+
+ Py_DECREF(item);
+ }
+
+ Py_DECREF(iterator);
+ return 0;
+}
+
+ static PyInt
+ListLength(PyObject *self)
+{
+ return ((PyInt) (((ListObject *) (self))->list->lv_len));
+}
+
+ static PyObject *
+ListItem(PyObject *self, Py_ssize_t index)
+{
+ listitem_T *li;
+
+ if (index>=ListLength(self))
+ {
+ PyErr_SetString(PyExc_IndexError, "list index out of range");
+ return NULL;
+ }
+ li = list_find(((ListObject *) (self))->list, (long) index);
+ if (li == NULL)
+ {
+ PyErr_SetVim(_("internal error: failed to get vim list item"));
+ return NULL;
+ }
+ return ConvertToPyObject(&li->li_tv);
+}
+
+#define PROC_RANGE \
+ if (last < 0) {\
+ if (last < -size) \
+ last = 0; \
+ else \
+ last += size; \
+ } \
+ if (first < 0) \
+ first = 0; \
+ if (first > size) \
+ first = size; \
+ if (last > size) \
+ last = size;
+
+ static PyObject *
+ListSlice(PyObject *self, Py_ssize_t first, Py_ssize_t last)
+{
+ PyInt i;
+ PyInt size = ListLength(self);
+ PyInt n;
+ PyObject *list;
+ int reversed = 0;
+
+ PROC_RANGE
+ if (first >= last)
+ first = last;
+
+ n = last-first;
+ list = PyList_New(n);
+ if (list == NULL)
+ return NULL;
+
+ for (i = 0; i < n; ++i)
+ {
+ PyObject *item = ListItem(self, i);
+ if (item == NULL)
+ {
+ Py_DECREF(list);
+ return NULL;
+ }
+
+ if ((PyList_SetItem(list, ((reversed)?(n-i-1):(i)), item)))
+ {
+ Py_DECREF(item);
+ Py_DECREF(list);
+ return NULL;
+ }
+ }
+
+ return list;
+}
+
+ static int
+ListAssItem(PyObject *self, Py_ssize_t index, PyObject *obj)
+{
+ typval_T tv;
+ list_T *l = ((ListObject *) (self))->list;
+ listitem_T *li;
+ Py_ssize_t length = ListLength(self);
+
+ if (l->lv_lock)
+ {
+ PyErr_SetVim(_("list is locked"));
+ return -1;
+ }
+ if (index>length || (index==length && obj==NULL))
+ {
+ PyErr_SetString(PyExc_IndexError, "list index out of range");
+ return -1;
+ }
+
+ if (obj == NULL)
+ {
+ li = list_find(l, (long) index);
+ list_remove(l, li, li);
+ clear_tv(&li->li_tv);
+ vim_free(li);
+ return 0;
+ }
+
+ if (ConvertFromPyObject(obj, &tv) == -1)
+ return -1;
+
+ if (index == length)
+ {
+ if (list_append_tv(l, &tv) == FAIL)
+ {
+ PyErr_SetVim(_("Failed to add item to list"));
+ return -1;
+ }
+ }
+ else
+ {
+ li = list_find(l, (long) index);
+ clear_tv(&li->li_tv);
+ copy_tv(&tv, &li->li_tv);
+ }
+ return 0;
+}
+
+ static int
+ListAssSlice(PyObject *self, Py_ssize_t first, Py_ssize_t last, PyObject *obj)
+{
+ PyInt size = ListLength(self);
+ Py_ssize_t i;
+ Py_ssize_t lsize;
+ PyObject *litem;
+ listitem_T *li;
+ listitem_T *next;
+ typval_T v;
+ list_T *l = ((ListObject *) (self))->list;
+
+ if (l->lv_lock)
+ {
+ PyErr_SetVim(_("list is locked"));
+ return -1;
+ }
+
+ PROC_RANGE
- for (hi = ht->ht_array; todo > 0; ++hi)
+ if (first == size)
+ li = NULL;
+ else
+ {
+ li = list_find(l, (long) first);
+ if (li == NULL)
+ {
+ PyErr_SetVim(_("internal error: no vim list item"));
+ return -1;
+ }
+ if (last > first)
+ {
+ i = last - first;
+ while (i-- && li != NULL)
{
- if (!HASHITEM_EMPTY(hi))
- {
- --todo;
-
- di = dict_lookup(hi);
- newObj = VimToPython(&di->di_tv, depth + 1, lookupDict);
- PyDict_SetItemString(result, (char *)hi->hi_key, newObj);
- Py_DECREF(newObj);
- }
+ next = li->li_next;
+ listitem_remove(l, li);
+ li = next;
}
}
}
- else
+
+ if (obj == NULL)
+ return 0;
+
+ if (!PyList_Check(obj))
{
- Py_INCREF(Py_None);
- result = Py_None;
+ PyErr_SetString(PyExc_TypeError, _("can only assign lists to slice"));
+ return -1;
}
- return result;
+ lsize = PyList_Size(obj);
+
+ for(i=0; i<lsize; i++)
+ {
+ litem = PyList_GetItem(obj, i);
+ if (litem == NULL)
+ return -1;
+ if (ConvertFromPyObject(litem, &v) == -1)
+ return -1;
+ if (list_insert_tv(l, &v, li) == FAIL)
+ {
+ PyErr_SetVim(_("internal error: failed to add item to list"));
+ return -1;
+ }
+ }
+ return 0;
}
-#endif
static PyObject *
-VimEval(PyObject *self UNUSED, PyObject *args UNUSED)
+ListConcatInPlace(PyObject *self, PyObject *obj)
{
-#ifdef FEAT_EVAL
- char *expr;
- typval_T *our_tv;
- PyObject *result;
- PyObject *lookup_dict;
+ list_T *l = ((ListObject *) (self))->list;
+ PyObject *lookup_dict;
- if (!PyArg_ParseTuple(args, "s", &expr))
+ if (l->lv_lock)
+ {
+ PyErr_SetVim(_("list is locked"));
return NULL;
+ }
- Py_BEGIN_ALLOW_THREADS
- Python_Lock_Vim();
- our_tv = eval_expr((char_u *)expr, NULL);
-
- Python_Release_Vim();
- Py_END_ALLOW_THREADS
-
- if (our_tv == NULL)
+ if (!PySequence_Check(obj))
{
- PyErr_SetVim(_("invalid expression"));
+ PyErr_SetString(PyExc_TypeError, _("can only concatenate with lists"));
return NULL;
}
- /* Convert the Vim type into a Python type. Create a dictionary that's
- * used to check for recursive loops. */
lookup_dict = PyDict_New();
- result = VimToPython(our_tv, 1, lookup_dict);
+ if (list_py_concat(l, obj, lookup_dict) == -1)
+ {
+ Py_DECREF(lookup_dict);
+ return NULL;
+ }
Py_DECREF(lookup_dict);
-
- Py_BEGIN_ALLOW_THREADS
- Python_Lock_Vim();
- free_tv(our_tv);
- Python_Release_Vim();
- Py_END_ALLOW_THREADS
-
- return result;
-#else
- PyErr_SetVim(_("expressions disabled at compile time"));
- return NULL;
-#endif
+ Py_INCREF(self);
+ return self;
}
-/*
- * Vim module - Definitions
- */
-
-static struct PyMethodDef VimMethods[] = {
- /* name, function, calling, documentation */
- {"command", VimCommand, 1, "Execute a Vim ex-mode command" },
- {"eval", VimEval, 1, "Evaluate an expression using Vim evaluator" },
- { NULL, NULL, 0, NULL }
+static struct PyMethodDef ListMethods[] = {
+ {"extend", (PyCFunction)ListConcatInPlace, METH_O, ""},
+ { NULL, NULL, 0, NULL }
};
typedef struct
{
PyObject_HEAD
- buf_T *buf;
-}
-BufferObject;
+ char_u *name;
+} FunctionObject;
-#define INVALID_BUFFER_VALUE ((buf_T *)(-1))
-
-/*
- * Buffer list object - Implementation
- */
+static PyTypeObject FunctionType;
- static PyInt
-BufListLength(PyObject *self UNUSED)
+ static PyObject *
+FunctionNew(char_u *name)
{
- buf_T *b = firstbuf;
- PyInt n = 0;
+ FunctionObject *self;
- while (b)
+ self = PyObject_NEW(FunctionObject, &FunctionType);
+ if (self == NULL)
+ return NULL;
+ self->name = PyMem_New(char_u, STRLEN(name) + 1);
+ if (self->name == NULL)
{
- ++n;
- b = b->b_next;
+ PyErr_NoMemory();
+ return NULL;
}
-
- return n;
+ STRCPY(self->name, name);
+ func_ref(name);
+ return (PyObject *)(self);
}
static PyObject *
-BufListItem(PyObject *self UNUSED, PyInt n)
+FunctionCall(PyObject *self, PyObject *argsObject, PyObject *kwargs)
{
- buf_T *b;
+ FunctionObject *this = (FunctionObject *)(self);
+ char_u *name = this->name;
+ typval_T args;
+ typval_T selfdicttv;
+ typval_T rettv;
+ dict_T *selfdict = NULL;
+ PyObject *selfdictObject;
+ PyObject *result;
+ int error;
- for (b = firstbuf; b; b = b->b_next, --n)
+ if (ConvertFromPyObject(argsObject, &args) == -1)
+ return NULL;
+
+ if (kwargs != NULL)
{
- if (n == 0)
- return BufferNew(b);
+ selfdictObject = PyDict_GetItemString(kwargs, "self");
+ if (selfdictObject != NULL)
+ {
+ if (!PyDict_Check(selfdictObject))
+ {
+ PyErr_SetString(PyExc_TypeError, _("'self' argument must be a dictionary"));
+ clear_tv(&args);
+ return NULL;
+ }
+ if (ConvertFromPyObject(selfdictObject, &selfdicttv) == -1)
+ return NULL;
+ selfdict = selfdicttv.vval.v_dict;
+ }
}
- PyErr_SetString(PyExc_IndexError, _("no such buffer"));
- return NULL;
+ error = func_call(name, &args, selfdict, &rettv);
+ if (error != OK)
+ {
+ result = NULL;
+ PyErr_SetVim(_("failed to run function"));
+ }
+ else
+ result = ConvertToPyObject(&rettv);
+
+ /* FIXME Check what should really be cleared. */
+ clear_tv(&args);
+ clear_tv(&rettv);
+ /*
+ * if (selfdict!=NULL)
+ * clear_tv(selfdicttv);
+ */
+
+ return result;
}
-typedef struct
-{
- PyObject_HEAD
- win_T *win;
-} WindowObject;
+static struct PyMethodDef FunctionMethods[] = {
+ {"__call__", (PyCFunction)FunctionCall, METH_VARARGS|METH_KEYWORDS, ""},
+ { NULL, NULL, 0, NULL }
+};
#define INVALID_WINDOW_VALUE ((win_T *)(-1))
@@ -1567,3 +2383,256 @@ static struct PyMethodDef RangeMethods[] = {
{ NULL, NULL, 0, NULL }
};
+ static void
+set_ref_in_py(const int copyID)
+{
+ pylinkedlist_T *cur;
+ dict_T *dd;
+ list_T *ll;
+
+ if (lastdict != NULL)
+ for(cur = lastdict ; cur != NULL ; cur = cur->pll_prev)
+ {
+ dd = ((DictionaryObject *) (cur->pll_obj))->dict;
+ if (dd->dv_copyID != copyID)
+ {
+ dd->dv_copyID = copyID;
+ set_ref_in_ht(&dd->dv_hashtab, copyID);
+ }
+ }
+
+ if (lastlist != NULL)
+ for(cur = lastlist ; cur != NULL ; cur = cur->pll_prev)
+ {
+ ll = ((ListObject *) (cur->pll_obj))->list;
+ if (ll->lv_copyID != copyID)
+ {
+ ll->lv_copyID = copyID;
+ set_ref_in_list(ll, copyID);
+ }
+ }
+}
+
+ static int
+set_string_copy(char_u *str, typval_T *tv)
+{
+ tv->vval.v_string = vim_strsave(str);
+ if (tv->vval.v_string == NULL)
+ {
+ PyErr_NoMemory();
+ return -1;
+ }
+ return 0;
+}
+
+#ifdef FEAT_EVAL
+typedef int (*pytotvfunc)(PyObject *, typval_T *, PyObject *);
+
+ static int
+convert_dl(PyObject *obj, typval_T *tv,
+ pytotvfunc py_to_tv, PyObject *lookupDict)
+{
+ PyObject *capsule;
+ char hexBuf[sizeof(void *) * 2 + 3];
+
+ sprintf(hexBuf, "%p", obj);
+
+ capsule = PyDict_GetItemString(lookupDict, hexBuf);
+ if (capsule == NULL)
+ {
+ capsule = PyCapsule_New(tv, NULL, NULL);
+ PyDict_SetItemString(lookupDict, hexBuf, capsule);
+ Py_DECREF(capsule);
+ if (py_to_tv(obj, tv, lookupDict) == -1)
+ {
+ tv->v_type = VAR_UNKNOWN;
+ return -1;
+ }
+ /* As we are not using copy_tv which increments reference count we must
+ * do it ourself. */
+ switch(tv->v_type)
+ {
+ case VAR_DICT: ++tv->vval.v_dict->dv_refcount; break;
+ case VAR_LIST: ++tv->vval.v_list->lv_refcount; break;
+ }
+ }
+ else
+ {
+ typval_T *v = PyCapsule_GetPointer(capsule, NULL);
+ copy_tv(v, tv);
+ }
+ return 0;
+}
+
+ static int
+ConvertFromPyObject(PyObject *obj, typval_T *tv)
+{
+ PyObject *lookup_dict;
+ int r;
+
+ lookup_dict = PyDict_New();
+ r = _ConvertFromPyObject(obj, tv, lookup_dict);
+ Py_DECREF(lookup_dict);
+ return r;
+}
+
+ static int
+_ConvertFromPyObject(PyObject *obj, typval_T *tv, PyObject *lookupDict)
+{
+ if (obj->ob_type == &DictionaryType)
+ {
+ tv->v_type = VAR_DICT;
+ tv->vval.v_dict = (((DictionaryObject *)(obj))->dict);
+ ++tv->vval.v_dict->dv_refcount;
+ }
+ else if (obj->ob_type == &ListType)
+ {
+ tv->v_type = VAR_LIST;
+ tv->vval.v_list = (((ListObject *)(obj))->list);
+ ++tv->vval.v_list->lv_refcount;
+ }
+ else if (obj->ob_type == &FunctionType)
+ {
+ if (set_string_copy(((FunctionObject *) (obj))->name, tv) == -1)
+ return -1;
+
+ tv->v_type = VAR_FUNC;
+ func_ref(tv->vval.v_string);
+ }
+#if PY_MAJOR_VERSION >= 3
+ else if (PyBytes_Check(obj))
+ {
+ char_u *result = (char_u *) PyBytes_AsString(obj);
+
+ if (result == NULL)
+ return -1;
+
+ if (set_string_copy(result, tv) == -1)
+ return -1;
+
+ tv->v_type = VAR_STRING;
+ }
+ else if (PyUnicode_Check(obj))
+ {
+ PyObject *bytes;
+ char_u *result;
+
+ bytes = PyString_AsBytes(obj);
+ if (bytes == NULL)
+ return -1;
+
+ result = (char_u *) PyBytes_AsString(bytes);
+ if (result == NULL)
+ return -1;
+
+ if (set_string_copy(result, tv) == -1)
+ {
+ Py_XDECREF(bytes);
+ return -1;
+ }
+ Py_XDECREF(bytes);
+
+ tv->v_type = VAR_STRING;
+ }
+#else
+ else if (PyUnicode_Check(obj))
+ {
+ PyObject *bytes;
+ char_u *result;
+
+ bytes = PyUnicode_AsEncodedString(obj, (char *)ENC_OPT, NULL);
+ if (bytes == NULL)
+ return -1;
+
+ result=(char_u *) PyString_AsString(bytes);
+ if (result == NULL)
+ return -1;
+
+ if (set_string_copy(result, tv) == -1)
+ {
+ Py_XDECREF(bytes);
+ return -1;
+ }
+ Py_XDECREF(bytes);
+
+ tv->v_type = VAR_STRING;
+ }
+ else if (PyString_Check(obj))
+ {
+ char_u *result = (char_u *) PyString_AsString(obj);
+
+ if (result == NULL)
+ return -1;
+
+ if (set_string_copy(result, tv) == -1)
+ return -1;
+
+ tv->v_type = VAR_STRING;
+ }
+ else if (PyInt_Check(obj))
+ {
+ tv->v_type = VAR_NUMBER;
+ tv->vval.v_number = (varnumber_T) PyInt_AsLong(obj);
+ }
+#endif
+ else if (PyLong_Check(obj))
+ {
+ tv->v_type = VAR_NUMBER;
+ tv->vval.v_number = (varnumber_T) PyLong_AsLong(obj);
+ }
+ else if (PyDict_Check(obj))
+ return convert_dl(obj, tv, pydict_to_tv, lookupDict);
+#ifdef FEAT_FLOAT
+ else if (PyFloat_Check(obj))
+ {
+ tv->v_type = VAR_FLOAT;
+ tv->vval.v_float = (float_T) PyFloat_AsDouble(obj);
+ }
+#endif
+ else if (PyIter_Check(obj))
+ return convert_dl(obj, tv, pyiter_to_tv, lookupDict);
+ else if (PySequence_Check(obj))
+ return convert_dl(obj, tv, pyseq_to_tv, lookupDict);
+ else if (PyMapping_Check(obj))
+ return convert_dl(obj, tv, pymap_to_tv, lookupDict);
+ else
+ {
+ PyErr_SetString(PyExc_TypeError, _("unable to convert to vim structure"));
+ return -1;
+ }
+ return 0;
+}
+
+ static PyObject *
+ConvertToPyObject(typval_T *tv)
+{
+ if (tv == NULL)
+ {
+ PyErr_SetVim(_("NULL reference passed"));
+ return NULL;
+ }
+ switch (tv->v_type)
+ {
+ case VAR_STRING:
+ return PyBytes_FromString((char *) tv->vval.v_string);
+ case VAR_NUMBER:
+ return PyLong_FromLong((long) tv->vval.v_number);
+#ifdef FEAT_FLOAT
+ case VAR_FLOAT:
+ return PyFloat_FromDouble((double) tv->vval.v_float);
+#endif
+ case VAR_LIST:
+ return ListNew(tv->vval.v_list);
+ case VAR_DICT:
+ return DictionaryNew(tv->vval.v_dict);
+ case VAR_FUNC:
+ return FunctionNew(tv->vval.v_string);
+ case VAR_UNKNOWN:
+ Py_INCREF(Py_None);
+ return Py_None;
+ default:
+ PyErr_SetVim(_("internal error: invalid value type"));
+ return NULL;
+ }
+}
+#endif
View
336 src/if_python.c
@@ -1,4 +1,4 @@
-/* vi:set ts=8 sts=4 sw=4:
+/* vi:set ts=8 sts=4 sw=4 noet:
*
* VIM - Vi IMproved by Bram Moolenaar
*
@@ -56,6 +56,8 @@
static void init_structs(void);
+#define PyBytes_FromString PyString_FromString
+
/* No-op conversion functions, use with care! */
#define PyString_AsBytes(obj) (obj)
#define PyString_FreeBytes(obj)
@@ -122,11 +124,13 @@ struct PyMethodDef { Py_ssize_t a; };
/* This makes if_python.c compile without warnings against Python 2.5
* on Win32 and Win64. */
# undef PyRun_SimpleString
+# undef PyRun_String
# undef PyArg_Parse
# undef PyArg_ParseTuple
# undef Py_BuildValue
# undef Py_InitModule4
# undef Py_InitModule4_64
+# undef PyObject_CallMethod
/*
* Wrapper defines
@@ -134,6 +138,7 @@ struct PyMethodDef { Py_ssize_t a; };
# define PyArg_Parse dll_PyArg_Parse
# define PyArg_ParseTuple dll_PyArg_ParseTuple
# define PyMem_Free dll_PyMem_Free
+# define PyMem_Malloc dll_PyMem_Malloc
# define PyDict_SetItemString dll_PyDict_SetItemString
# define PyErr_BadArgument dll_PyErr_BadArgument
# define PyErr_Clear dll_PyErr_Clear
@@ -150,23 +155,48 @@ struct PyMethodDef { Py_ssize_t a; };
# endif
# define PyInt_AsLong dll_PyInt_AsLong
# define PyInt_FromLong dll_PyInt_FromLong
+# define PyLong_AsLong dll_PyLong_AsLong
+# define PyLong_FromLong dll_PyLong_FromLong
# define PyInt_Type (*dll_PyInt_Type)
+# define PyLong_Type (*dll_PyLong_Type)
# define PyList_GetItem dll_PyList_GetItem
# define PyList_Append dll_PyList_Append
# define PyList_New dll_PyList_New
# define PyList_SetItem dll_PyList_SetItem
# define PyList_Size dll_PyList_Size
# define PyList_Type (*dll_PyList_Type)
+# define PySequence_Check dll_PySequence_Check
+# define PySequence_Size dll_PySequence_Size
+# define PySequence_GetItem dll_PySequence_GetItem
+# define PyTuple_Size dll_PyTuple_Size
+# define PyTuple_GetItem dll_PyTuple_GetItem
+# define PyTuple_Type (*dll_PyTuple_Type)
# define PyImport_ImportModule dll_PyImport_ImportModule
# define PyDict_New dll_PyDict_New
# define PyDict_GetItemString dll_PyDict_GetItemString
+# define PyDict_Next dll_PyDict_Next
+# ifdef PyMapping_Items
+# define PY_NO_MAPPING_ITEMS
+# else
+# define PyMapping_Items dll_PyMapping_Items
+# endif
+# define PyObject_CallMethod dll_PyObject_CallMethod
+# define PyMapping_Check dll_PyMapping_Check
+# define PyIter_Next dll_PyIter_Next
# define PyModule_GetDict dll_PyModule_GetDict
# define PyRun_SimpleString dll_PyRun_SimpleString
+# define PyRun_String dll_PyRun_String
# define PyString_AsString dll_PyString_AsString
# define PyString_FromString dll_PyString_FromString
# define PyString_FromStringAndSize dll_PyString_FromStringAndSize
# define PyString_Size dll_PyString_Size
# define PyString_Type (*dll_PyString_Type)
+# define PyUnicode_Type (*dll_PyUnicode_Type)
+# define PyUnicodeUCS4_AsEncodedString (*dll_PyUnicodeUCS4_AsEncodedString)
+# define PyFloat_AsDouble dll_PyFloat_AsDouble
+# define PyFloat_FromDouble dll_PyFloat_FromDouble
+# define PyFloat_Type (*dll_PyFloat_Type)
+# define PyImport_AddModule (*dll_PyImport_AddModule)
# define PySys_SetObject dll_PySys_SetObject
# define PySys_SetArgv dll_PySys_SetArgv
# define PyType_Type (*dll_PyType_Type)
@@ -179,8 +209,10 @@ struct PyMethodDef { Py_ssize_t a; };
# define Py_Finalize dll_Py_Finalize
# define Py_IsInitialized dll_Py_IsInitialized
# define _PyObject_New dll__PyObject_New
+# define _PyObject_NextNotImplemented (*dll__PyObject_NextNotImplemented)
# define _Py_NoneStruct (*dll__Py_NoneStruct)
# define PyObject_Init dll__PyObject_Init
+# define PyObject_GetIter dll_PyObject_GetIter
# if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000
# define PyType_IsSubtype dll_PyType_IsSubtype
# endif
@@ -188,6 +220,8 @@ struct PyMethodDef { Py_ssize_t a; };
# define PyObject_Malloc dll_PyObject_Malloc
# define PyObject_Free dll_PyObject_Free
# endif
+# define PyCapsule_New dll_PyCapsule_New
+# define PyCapsule_GetPointer dll_PyCapsule_GetPointer
/*
* Pointers for dynamic link
@@ -195,6 +229,7 @@ struct PyMethodDef { Py_ssize_t a; };
static int(*dll_PyArg_Parse)(PyObject *, char *, ...);
static int(*dll_PyArg_ParseTuple)(PyObject *, char *, ...);
static int(*dll_PyMem_Free)(void *);
+static void* (*dll_PyMem_Malloc)(size_t);
static int(*dll_PyDict_SetItemString)(PyObject *dp, char *key, PyObject *item);
static int(*dll_PyErr_BadArgument)(void);
static void(*dll_PyErr_Clear)(void);
@@ -208,26 +243,48 @@ static PyThreadState*(*dll_PyEval_SaveThread)(void);
# ifdef PY_CAN_RECURSE
static PyGILState_STATE (*dll_PyGILState_Ensure)(void);
static void (*dll_PyGILState_Release)(PyGILState_STATE);
-#endif
+# endif
static long(*dll_PyInt_AsLong)(PyObject *);
static PyObject*(*dll_PyInt_FromLong)(long);
+static long(*dll_PyLong_AsLong)(PyObject *);
+static PyObject*(*dll_PyLong_FromLong)(long);
static PyTypeObject* dll_PyInt_Type;
+static PyTypeObject* dll_PyLong_Type;
static PyObject*(*dll_PyList_GetItem)(PyObject *, PyInt);
static PyObject*(*dll_PyList_Append)(PyObject *, PyObject *);
static PyObject*(*dll_PyList_New)(PyInt size);
static int(*dll_PyList_SetItem)(PyObject *, PyInt, PyObject *);
static PyInt(*dll_PyList_Size)(PyObject *);
static PyTypeObject* dll_PyList_Type;
+static int (*dll_PySequence_Check)(PyObject *);
+static PyInt(*dll_PySequence_Size)(PyObject *);
+static PyObject*(*dll_PySequence_GetItem)(PyObject *, PyInt);
+static PyInt(*dll_PyTuple_Size)(PyObject *);
+static PyObject*(*dll_PyTuple_GetItem)(PyObject *, PyInt);
+static PyTypeObject* dll_PyTuple_Type;
static PyObject*(*dll_PyImport_ImportModule)(const char *);
static PyObject*(*dll_PyDict_New)(void);
static PyObject*(*dll_PyDict_GetItemString)(PyObject *, const char *);
+static int (*dll_PyDict_Next)(PyObject *, Py_ssize_t *, PyObject **, PyObject **);
+# ifndef PY_NO_MAPPING_ITEMS
+static PyObject* (*dll_PyMapping_Items)(PyObject *);
+# endif
+static PyObject* (*dll_PyObject_CallMethod)(PyObject *, char *, PyObject *);
+static int (*dll_PyMapping_Check)(PyObject *);
+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 char*(*dll_PyString_AsString)(PyObject *);
static PyObject*(*dll_PyString_FromString)(const char *);
static PyObject*(*dll_PyString_FromStringAndSize)(const char *, PyInt);
static PyInt(*dll_PyString_Size)(PyObject *);
static PyTypeObject* dll_PyString_Type;
+static PyTypeObject* dll_PyUnicode_Type;
+static PyObject *(*PyUnicodeUCS4_AsEncodedString)(PyObject *, char *, char *);
+static double(*dll_PyFloat_AsDouble)(PyObject *);
+static PyObject*(*dll_PyFloat_FromDouble)(double);
+static PyTypeObject* dll_PyFloat_Type;
static int(*dll_PySys_SetObject)(char *, PyObject *);
static int(*dll_PySys_SetArgv)(int, char **);
static PyTypeObject* dll_PyType_Type;
@@ -235,12 +292,15 @@ static int (*dll_PyType_Ready)(PyTypeObject *type);
static PyObject*(*dll_Py_BuildValue)(char *, ...);
static PyObject*(*dll_Py_FindMethod)(struct PyMethodDef[], PyObject *, char *);
static PyObject*(*dll_Py_InitModule4)(char *, struct PyMethodDef *, char *, PyObject *, int);
+static PyObject*(*dll_PyImport_AddModule)(char *);
static void(*dll_Py_SetPythonHome)(char *home);
static void(*dll_Py_Initialize)(void);
static void(*dll_Py_Finalize)(void);
static int(*dll_Py_IsInitialized)(void);
static PyObject*(*dll__PyObject_New)(PyTypeObject *, PyObject *);
static PyObject*(*dll__PyObject_Init)(PyObject *, PyTypeObject *);
+static PyObject* (*dll_PyObject_GetIter)(PyObject *);
+static iternextfunc dll__PyObject_NextNotImplemented;
static PyObject* dll__Py_NoneStruct;
# if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000
static int (*dll_PyType_IsSubtype)(PyTypeObject *, PyTypeObject *);
@@ -249,6 +309,8 @@ static int (*dll_PyType_IsSubtype)(PyTypeObject *, PyTypeObject *);
static void* (*dll_PyObject_Malloc)(size_t);
static void (*dll_PyObject_Free)(void*);
# endif
+static PyObject* (*dll_PyCapsule_New)(void *, char *, PyCapsule_Destructor);
+static void* (*dll_PyCapsule_GetPointer)(PyObject *, char *);
static HINSTANCE hinstPython = 0; /* Instance of python.dll */
@@ -278,6 +340,7 @@ static struct
{"PyArg_Parse", (PYTHON_PROC*)&dll_PyArg_Parse},
{"PyArg_ParseTuple", (PYTHON_PROC*)&dll_PyArg_ParseTuple},
{"PyMem_Free", (PYTHON_PROC*)&dll_PyMem_Free},
+ {"PyMem_Malloc", (PYTHON_PROC*)&dll_PyMem_Malloc},
{"PyDict_SetItemString", (PYTHON_PROC*)&dll_PyDict_SetItemString},
{"PyErr_BadArgument", (PYTHON_PROC*)&dll_PyErr_BadArgument},
{"PyErr_Clear", (PYTHON_PROC*)&dll_PyErr_Clear},
@@ -294,23 +357,46 @@ static struct
# endif
{"PyInt_AsLong", (PYTHON_PROC*)&dll_PyInt_AsLong},
{"PyInt_FromLong", (PYTHON_PROC*)&dll_PyInt_FromLong},
+ {"PyLong_AsLong", (PYTHON_PROC*)&dll_PyLong_AsLong},
+ {"PyLong_FromLong", (PYTHON_PROC*)&dll_PyLong_FromLong},
{"PyInt_Type", (PYTHON_PROC*)&dll_PyInt_Type},
+ {"PyLong_Type", (PYTHON_PROC*)&dll_PyLong_Type},
{"PyList_GetItem", (PYTHON_PROC*)&dll_PyList_GetItem},
{"PyList_Append", (PYTHON_PROC*)&dll_PyList_Append},
{"PyList_New", (PYTHON_PROC*)&dll_PyList_New},
{"PyList_SetItem", (PYTHON_PROC*)&dll_PyList_SetItem},
{"PyList_Size", (PYTHON_PROC*)&dll_PyList_Size},
{"PyList_Type", (PYTHON_PROC*)&dll_PyList_Type},
+ {"PySequence_GetItem", (PYTHON_PROC*)&dll_PySequence_GetItem},
+ {"PySequence_Size", (PYTHON_PROC*)&dll_PySequence_Size},
+ {"PySequence_Check", (PYTHON_PROC*)&dll_PySequence_Check},
+ {"PyTuple_GetItem", (PYTHON_PROC*)&dll_PyTuple_GetItem},
+ {"PyTuple_Size", (PYTHON_PROC*)&dll_PyTuple_Size},
+ {"PyTuple_Type", (PYTHON_PROC*)&dll_PyTuple_Type},
{"PyImport_ImportModule", (PYTHON_PROC*)&dll_PyImport_ImportModule},
{"PyDict_GetItemString", (PYTHON_PROC*)&dll_PyDict_GetItemString},
+ {"PyDict_Next", (PYTHON_PROC*)&dll_PyDict_Next},
{"PyDict_New", (PYTHON_PROC*)&dll_PyDict_New},
+# ifndef PY_NO_MAPPING_ITEMS
+ {"PyMapping_Items", (PYTHON_PROC*)&dll_PyMapping_Items},
+# endif
+ {"PyObject_CallMethod", (PYTHON_PROC*)&dll_PyObject_CallMethod},
+ {"PyMapping_Check", (PYTHON_PROC*)&dll_PyMapping_Check},
+ {"PyIter_Next", (PYTHON_PROC*)&dll_PyIter_Next},
{"PyModule_GetDict", (PYTHON_PROC*)&dll_PyModule_GetDict},
{"PyRun_SimpleString", (PYTHON_PROC*)&dll_PyRun_SimpleString},
+ {"PyRun_String", (PYTHON_PROC*)&dll_PyRun_String},
{"PyString_AsString", (PYTHON_PROC*)&dll_PyString_AsString},
{"PyString_FromString", (PYTHON_PROC*)&dll_PyString_FromString},
{"PyString_FromStringAndSize", (PYTHON_PROC*)&dll_PyString_FromStringAndSize},
{"PyString_Size", (PYTHON_PROC*)&dll_PyString_Size},
{"PyString_Type", (PYTHON_PROC*)&dll_PyString_Type},
+ {"PyUnicode_Type", (PYTHON_PROC*)&dll_PyUnicode_Type},
+ {"PyUnicodeUCS4_AsEncodedString", (PYTHON_PROC*)&dll_PyUnicodeUCS4_AsEncodedString},
+ {"PyFloat_Type", (PYTHON_PROC*)&dll_PyFloat_Type},
+ {"PyFloat_AsDouble", (PYTHON_PROC*)&dll_PyFloat_AsDouble},
+ {"PyFloat_FromDouble", (PYTHON_PROC*)&dll_PyFloat_FromDouble},
+ {"PyImport_AddModule", (PYTHON_PROC*)&dll_PyImport_AddModule},
{"PySys_SetObject", (PYTHON_PROC*)&dll_PySys_SetObject},
{"PySys_SetArgv", (PYTHON_PROC*)&dll_PySys_SetArgv},
{"PyType_Type", (PYTHON_PROC*)&dll_PyType_Type},
@@ -328,6 +414,8 @@ static struct
{"Py_IsInitialized", (PYTHON_PROC*)&dll_Py_IsInitialized},
{"_PyObject_New", (PYTHON_PROC*)&dll__PyObject_New},
{"PyObject_Init", (PYTHON_PROC*)&dll__PyObject_Init},
+ {"PyObject_GetIter", (PYTHON_PROC*)&dll_PyObject_GetIter},
+ {"_PyObject_NextNotImplemented", (PYTHON_PROC*)&dll__PyObject_NextNotImplemented},
{"_Py_NoneStruct", (PYTHON_PROC*)&dll__Py_NoneStruct},
# if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000
{"PyType_IsSubtype", (PYTHON_PROC*)&dll_PyType_IsSubtype},
@@ -336,6 +424,8 @@ static struct
{"PyObject_Malloc", (PYTHON_PROC*)&dll_PyObject_Malloc},
{"PyObject_Free", (PYTHON_PROC*)&dll_PyObject_Free},
# endif
+ {"PyCapsule_New", (PYTHON_PROC*)&dll_PyCapsule_New},
+ {"PyCapsule_GetPointer", (PYTHON_PROC*)&dll_PyCapsule_GetPointer},
{"", NULL},
};
@@ -434,10 +524,25 @@ get_exceptions(void)
static PyObject *BufferNew (buf_T *);
static PyObject *WindowNew(win_T *);
+static PyObject *DictionaryNew(dict_T *);
static PyObject *LineToString(const char *);
static PyTypeObject RangeType;
+static int initialised = 0;
+#define PYINITIALISED initialised
+
+/* Add conversion from PyInt? */
+#define DICTKEY_GET(err) \
+ if (!PyString_Check(keyObject)) \
+ { \
+ PyErr_SetString(PyExc_TypeError, _("only string keys are allowed")); \
+ return err; \
+ } \
+ key = (char_u *) PyString_AsString(keyObject);
+#define DICTKEY_UNREF
+#define DICTKEY_DECL
+
/*
* Include the code shared with if_python3.c
*/
@@ -451,6 +556,8 @@ static PyTypeObject RangeType;
static PyInt RangeStart;
static PyInt RangeEnd;
+static PyObject *globals;
+
static void PythonIO_Flush(void);
static int PythonIO_Init(void);
static int PythonMod_Init(void);
@@ -466,8 +573,6 @@ static int SetBufferLineList(buf_T *, PyInt, PyInt, PyObject *, PyInt *);
* 1. Python interpreter main program.
*/
-static int initialised = 0;
-
#if PYTHON_API_VERSION < 1007 /* Python 1.4 */
typedef PyObject PyThreadState;
#endif
@@ -581,6 +686,8 @@ Python_Init(void)
if (PythonMod_Init())
goto fail;
+ globals = PyModule_GetDict(PyImport_AddModule("__main__"));
+
/* Remove the element from sys.path that was added because of our
* argv[0] value in PythonMod_Init(). Previously we used an empty
* string, but dependinding on the OS we then get an empty entry or
@@ -609,7 +716,7 @@ Python_Init(void)
* External interface
*/
static void
-DoPythonCommand(exarg_T *eap, const char *cmd)
+DoPythonCommand(exarg_T *eap, const char *cmd, typval_T *rettv)
{
#ifndef PY_CAN_RECURSE
static int recursive = 0;
@@ -639,8 +746,16 @@ DoPythonCommand(exarg_T *eap, const char *cmd)
if (Python_Init())
goto theend;
- RangeStart = eap->line1;
- RangeEnd = eap->line2;
+ if (rettv == NULL)
+ {
+ RangeStart = eap->line1;
+ RangeEnd = eap->line2;
+ }
+ else
+ {
+ RangeStart = (PyInt) curwin->w_cursor.lnum;
+ RangeEnd = RangeStart;
+ }
Python_Release_Vim(); /* leave vim */
#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
@@ -658,7 +773,23 @@ DoPythonCommand(exarg_T *eap, const char *cmd)
Python_RestoreThread(); /* enter python */
- PyRun_SimpleString((char *)(cmd));
+ if (rettv == NULL)
+ PyRun_SimpleString((char *)(cmd));
+ else
+ {
+ PyObject *r;
+
+ r = PyRun_String((char *)(cmd), Py_eval_input, globals, globals);
+ if (r == NULL)
+ EMSG(_("E858: Eval did not return a valid python object"));
+ else
+ {
+ if (ConvertFromPyObject(r, rettv) == -1)
+ EMSG(_("E859: Failed to convert returned python object to vim value"));
+ Py_DECREF(r);
+ }
+ PyErr_Clear();
+ }
Python_SaveThread(); /* leave python */
@@ -680,7 +811,7 @@ DoPythonCommand(exarg_T *eap, const char *cmd)
#ifndef PY_CAN_RECURSE
--recursive;
#endif
- return; /* keeps lint happy */
+ return;
}
/*
@@ -695,9 +826,9 @@ ex_python(exarg_T *eap)
if (!eap->skip)
{
if (script == NULL)
- DoPythonCommand(eap, (char *)eap->arg);
+ DoPythonCommand(eap, (char *)eap->arg, NULL);
else
- DoPythonCommand(eap, (char *)script);
+ DoPythonCommand(eap, (char *)script, NULL);
}
vim_free(script);
}
@@ -743,7 +874,7 @@ ex_pyfile(exarg_T *eap)
*p++ = '\0';
/* Execute the file */
- DoPythonCommand(eap, buffer);
+ DoPythonCommand(eap, buffer, NULL);
}
/******************************************************
@@ -765,14 +896,16 @@ OutputGetattr(PyObject *self, char *name)
static int
OutputSetattr(PyObject *self, char *name, PyObject *val)
{
- if (val == NULL) {
+ if (val == NULL)
+ {
PyErr_SetString(PyExc_AttributeError, _("can't delete OutputObject attributes"));
return -1;
}
if (strcmp(name, "softspace") == 0)
{
- if (!PyInt_Check(val)) {
+ if (!PyInt_Check(val))
+ {
PyErr_SetString(PyExc_TypeError, _("softspace must be an integer"));
return -1;
}
@@ -800,6 +933,9 @@ PythonIO_Init(void)
* 3. Implementation of the Vim module for Python
*/
+static PyObject *ConvertToPyObject(typval_T *);
+static int ConvertFromPyObject(PyObject *, typval_T *);
+
/* Window type - Implementation functions
* --------------------------------------
*/
@@ -1441,6 +1577,172 @@ LineToString(const char *str)
return result;
}
+static void DictionaryDestructor(PyObject *);
+static PyObject *DictionaryGetattr(PyObject *, char*);
+
+static PyMappingMethods DictionaryAsMapping = {
+ (PyInquiry) DictionaryLength,
+ (binaryfunc) DictionaryItem,
+ (objobjargproc) DictionaryAssItem,
+};
+
+static PyTypeObject DictionaryType = {
+ PyObject_HEAD_INIT(0)
+ 0,
+ "vimdictionary",
+ sizeof(DictionaryObject),
+ 0,
+
+ (destructor) DictionaryDestructor,
+ (printfunc) 0,
+ (getattrfunc) DictionaryGetattr,
+ (setattrfunc) 0,
+ (cmpfunc) 0,
+ (reprfunc) 0,
+
+ 0, /* as number */
+ 0, /* as sequence */
+ &DictionaryAsMapping, /* as mapping */
+
+ (hashfunc) 0,
+ (ternaryfunc) 0,
+ (reprfunc) 0,
+};
+
+ static void
+DictionaryDestructor(PyObject *self)
+{
+ DictionaryObject *this = ((DictionaryObject *) (self));
+
+ pyll_remove(&this->ref, &lastdict);
+ dict_unref(this->dict);
+
+ Py_DECREF(self);
+}
+
+ static PyObject *
+DictionaryGetattr(PyObject *self, char *name)
+{
+ return Py_FindMethod(DictionaryMethods, self, name);
+}
+
+static void ListDestructor(PyObject *);
+static PyObject *ListGetattr(PyObject *, char *);
+
+static PySequenceMethods ListAsSeq = {
+ (PyInquiry) ListLength,
+ (binaryfunc) 0,
+ (PyIntArgFunc) 0,
+ (PyIntArgFunc) ListItem,
+ (PyIntIntArgFunc) ListSlice,
+ (PyIntObjArgProc) ListAssItem,
+ (PyIntIntObjArgProc) ListAssSlice,
+ (objobjproc) 0,
+#if PY_MAJOR_VERSION >= 2
+ (binaryfunc) ListConcatInPlace,
+ 0,
+#endif
+};
+
+static PyTypeObject ListType = {
+ PyObject_HEAD_INIT(0)
+ 0,
+ "vimlist",
+ sizeof(ListObject),
+ 0,
+
+ (destructor) ListDestructor,
+ (printfunc) 0,
+ (getattrfunc) ListGetattr,
+ (setattrfunc) 0,
+ (cmpfunc) 0,
+ (reprfunc) 0,
+
+ 0, /* as number */
+ &ListAsSeq, /* as sequence */
+ 0, /* as mapping */
+
+ (hashfunc) 0,
+ (ternaryfunc) 0,
+ (reprfunc) 0,
+};
+
+ static void
+ListDestructor(PyObject *self)
+{
+ ListObject *this = ((ListObject *) (self));
+
+ pyll_remove(&this->ref, &lastlist);
+ list_unref(this->list);
+
+ Py_DECREF(self);
+}
+
+ static PyObject *
+ListGetattr(PyObject *self, char *name)
+{
+ return Py_FindMethod(ListMethods, self, name);
+}
+
+static void FunctionDestructor(PyObject *);
+static PyObject *FunctionGetattr(PyObject *, char *);
+
+static PyTypeObject FunctionType = {
+ PyObject_HEAD_INIT(0)
+ 0,
+ "vimfunction",
+ sizeof(FunctionObject),
+ 0,
+
+ (destructor) FunctionDestructor,
+ (printfunc) 0,
+ (getattrfunc) FunctionGetattr,
+ (setattrfunc) 0,
+ (cmpfunc) 0,
+ (reprfunc) 0,
+
+ 0, /* as number */
+ 0, /* as sequence */
+ 0, /* as mapping */
+
+ (hashfunc) 0,
+ (ternaryfunc) FunctionCall,
+ (reprfunc) 0,
+};
+
+ static void
+FunctionDestructor(PyObject *self)
+{
+ FunctionObject *this = (FunctionObject *) (self);
+
+ func_unref(this->name);
+ PyMem_Del(this->name);
+
+ Py_DECREF(self);
+}
+
+ static PyObject *
+FunctionGetattr(PyObject *self, char *name)
+{
+ FunctionObject *this = (FunctionObject *)(self);
+
+ if (strcmp(name, "name") == 0)
+ return PyString_FromString((char *)(this->name));
+ else
+ return Py_FindMethod(FunctionMethods, self, name);
+}
+
+ void
+do_pyeval (char_u *str, typval_T *rettv)
+{
+ DoPythonCommand(NULL, (char *) str, rettv);