forked from aniani/vim
updated for version 7.3.947
Problem: Python: No iterator for vim.list and vim.bufferlist. Solution: Add the iterators. Also fix name of FunctionType. Add tests for vim.buffers. (ZyX)
This commit is contained in:
@@ -214,6 +214,7 @@ vim.buffers *python-buffers*
|
|||||||
:py b = vim.buffers[i] # Indexing (read-only)
|
:py b = vim.buffers[i] # Indexing (read-only)
|
||||||
:py b in vim.buffers # Membership test
|
:py b in vim.buffers # Membership test
|
||||||
:py n = len(vim.buffers) # Number of elements
|
:py n = len(vim.buffers) # Number of elements
|
||||||
|
:py for b in vim.buffers: # Iterating over buffer list
|
||||||
<
|
<
|
||||||
vim.windows *python-windows*
|
vim.windows *python-windows*
|
||||||
A sequence object providing access to the list of vim windows. The
|
A sequence object providing access to the list of vim windows. The
|
||||||
|
@@ -390,8 +390,6 @@ static char_u *get_lval __ARGS((char_u *name, typval_T *rettv, lval_T *lp, int u
|
|||||||
static void clear_lval __ARGS((lval_T *lp));
|
static void clear_lval __ARGS((lval_T *lp));
|
||||||
static void set_var_lval __ARGS((lval_T *lp, char_u *endp, typval_T *rettv, int copy, char_u *op));
|
static void set_var_lval __ARGS((lval_T *lp, char_u *endp, typval_T *rettv, int copy, char_u *op));
|
||||||
static int tv_op __ARGS((typval_T *tv1, typval_T *tv2, char_u *op));
|
static int tv_op __ARGS((typval_T *tv1, typval_T *tv2, char_u *op));
|
||||||
static void list_add_watch __ARGS((list_T *l, listwatch_T *lw));
|
|
||||||
static void list_rem_watch __ARGS((list_T *l, listwatch_T *lwrem));
|
|
||||||
static void list_fix_watch __ARGS((list_T *l, listitem_T *item));
|
static void list_fix_watch __ARGS((list_T *l, listitem_T *item));
|
||||||
static void ex_unletlock __ARGS((exarg_T *eap, char_u *argstart, int deep));
|
static void ex_unletlock __ARGS((exarg_T *eap, char_u *argstart, int deep));
|
||||||
static int do_unlet_var __ARGS((lval_T *lp, char_u *name_end, int forceit));
|
static int do_unlet_var __ARGS((lval_T *lp, char_u *name_end, int forceit));
|
||||||
@@ -3106,7 +3104,7 @@ tv_op(tv1, tv2, op)
|
|||||||
/*
|
/*
|
||||||
* Add a watcher to a list.
|
* Add a watcher to a list.
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
list_add_watch(l, lw)
|
list_add_watch(l, lw)
|
||||||
list_T *l;
|
list_T *l;
|
||||||
listwatch_T *lw;
|
listwatch_T *lw;
|
||||||
@@ -3119,7 +3117,7 @@ list_add_watch(l, lw)
|
|||||||
* Remove a watcher from a list.
|
* Remove a watcher from a list.
|
||||||
* No warning when it isn't found...
|
* No warning when it isn't found...
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
list_rem_watch(l, lwrem)
|
list_rem_watch(l, lwrem)
|
||||||
list_T *l;
|
list_T *l;
|
||||||
listwatch_T *lwrem;
|
listwatch_T *lwrem;
|
||||||
|
253
src/if_py_both.h
253
src/if_py_both.h
@@ -531,66 +531,62 @@ static struct PyMethodDef VimMethods[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Buffer list object - Implementation
|
* Generic iterator object
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static PyTypeObject BufMapType;
|
static PyTypeObject IterType;
|
||||||
|
|
||||||
|
typedef PyObject *(*nextfun)(void **);
|
||||||
|
typedef void (*destructorfun)(void *);
|
||||||
|
|
||||||
|
/* Main purpose of this object is removing the need for do python initialization
|
||||||
|
* (i.e. PyType_Ready and setting type attributes) for a big bunch of objects.
|
||||||
|
*/
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
} BufMapObject;
|
void *cur;
|
||||||
|
nextfun next;
|
||||||
|
destructorfun destruct;
|
||||||
|
} IterObject;
|
||||||
|
|
||||||
static PyInt
|
static PyObject *
|
||||||
BufMapLength(PyObject *self UNUSED)
|
IterNew(void *start, destructorfun destruct, nextfun next)
|
||||||
{
|
{
|
||||||
buf_T *b = firstbuf;
|
IterObject *self;
|
||||||
PyInt n = 0;
|
|
||||||
|
|
||||||
while (b)
|
self = PyObject_NEW(IterObject, &IterType);
|
||||||
{
|
self->cur = start;
|
||||||
++n;
|
self->next = next;
|
||||||
b = b->b_next;
|
self->destruct = destruct;
|
||||||
}
|
|
||||||
|
|
||||||
return n;
|
return (PyObject *)(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
IterDestructor(PyObject *self)
|
||||||
|
{
|
||||||
|
IterObject *this = (IterObject *)(self);
|
||||||
|
|
||||||
|
this->destruct(this->cur);
|
||||||
|
|
||||||
|
DESTRUCTOR_FINISH(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
BufMapItem(PyObject *self UNUSED, PyObject *keyObject)
|
IterNext(PyObject *self)
|
||||||
{
|
{
|
||||||
buf_T *b;
|
IterObject *this = (IterObject *)(self);
|
||||||
int bnr;
|
|
||||||
|
|
||||||
#if PY_MAJOR_VERSION < 3
|
return this->next(&this->cur);
|
||||||
if (PyInt_Check(keyObject))
|
|
||||||
bnr = PyInt_AsLong(keyObject);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
if (PyLong_Check(keyObject))
|
|
||||||
bnr = PyLong_AsLong(keyObject);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PyErr_SetString(PyExc_ValueError, _("key must be integer"));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
b = buflist_findnr(bnr);
|
|
||||||
|
|
||||||
if (b)
|
|
||||||
return BufferNew(b);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PyErr_SetString(PyExc_KeyError, _("no such buffer"));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyMappingMethods BufMapAsMapping = {
|
static PyObject *
|
||||||
(lenfunc) BufMapLength,
|
IterIter(PyObject *self)
|
||||||
(binaryfunc) BufMapItem,
|
{
|
||||||
(objobjargproc) 0,
|
return self;
|
||||||
};
|
}
|
||||||
|
|
||||||
typedef struct pylinkedlist_S {
|
typedef struct pylinkedlist_S {
|
||||||
struct pylinkedlist_S *pll_next;
|
struct pylinkedlist_S *pll_next;
|
||||||
@@ -990,6 +986,55 @@ ListSlice(PyObject *self, Py_ssize_t first, Py_ssize_t last)
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
listwatch_T lw;
|
||||||
|
list_T *list;
|
||||||
|
} listiterinfo_T;
|
||||||
|
|
||||||
|
static void
|
||||||
|
ListIterDestruct(listiterinfo_T *lii)
|
||||||
|
{
|
||||||
|
list_rem_watch(lii->list, &lii->lw);
|
||||||
|
PyMem_Free(lii);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
ListIterNext(listiterinfo_T **lii)
|
||||||
|
{
|
||||||
|
PyObject *r;
|
||||||
|
|
||||||
|
if (!((*lii)->lw.lw_item))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!(r = ConvertToPyObject(&((*lii)->lw.lw_item->li_tv))))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
(*lii)->lw.lw_item = (*lii)->lw.lw_item->li_next;
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
ListIter(PyObject *self)
|
||||||
|
{
|
||||||
|
listiterinfo_T *lii;
|
||||||
|
list_T *l = ((ListObject *) (self))->list;
|
||||||
|
|
||||||
|
if (!(lii = PyMem_New(listiterinfo_T, 1)))
|
||||||
|
{
|
||||||
|
PyErr_NoMemory();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_add_watch(l, &lii->lw);
|
||||||
|
lii->lw.lw_item = l->lv_first;
|
||||||
|
lii->list = l;
|
||||||
|
|
||||||
|
return IterNew(lii,
|
||||||
|
(destructorfun) ListIterDestruct, (nextfun) ListIterNext);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ListAssItem(PyObject *self, Py_ssize_t index, PyObject *obj)
|
ListAssItem(PyObject *self, Py_ssize_t index, PyObject *obj)
|
||||||
{
|
{
|
||||||
@@ -2869,6 +2914,116 @@ static struct PyMethodDef BufferMethods[] = {
|
|||||||
{ NULL, NULL, 0, NULL }
|
{ NULL, NULL, 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Buffer list object - Implementation
|
||||||
|
*/
|
||||||
|
|
||||||
|
static PyTypeObject BufMapType;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
PyObject_HEAD
|
||||||
|
} BufMapObject;
|
||||||
|
|
||||||
|
static PyInt
|
||||||
|
BufMapLength(PyObject *self UNUSED)
|
||||||
|
{
|
||||||
|
buf_T *b = firstbuf;
|
||||||
|
PyInt n = 0;
|
||||||
|
|
||||||
|
while (b)
|
||||||
|
{
|
||||||
|
++n;
|
||||||
|
b = b->b_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
BufMapItem(PyObject *self UNUSED, PyObject *keyObject)
|
||||||
|
{
|
||||||
|
buf_T *b;
|
||||||
|
int bnr;
|
||||||
|
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
if (PyInt_Check(keyObject))
|
||||||
|
bnr = PyInt_AsLong(keyObject);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if (PyLong_Check(keyObject))
|
||||||
|
bnr = PyLong_AsLong(keyObject);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_ValueError, _("key must be integer"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
b = buflist_findnr(bnr);
|
||||||
|
|
||||||
|
if (b)
|
||||||
|
return BufferNew(b);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_KeyError, _("no such buffer"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
BufMapIterDestruct(PyObject *buffer)
|
||||||
|
{
|
||||||
|
/* Iteration was stopped before all buffers were processed */
|
||||||
|
if (buffer)
|
||||||
|
{
|
||||||
|
Py_DECREF(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
BufMapIterNext(PyObject **buffer)
|
||||||
|
{
|
||||||
|
PyObject *next;
|
||||||
|
PyObject *r;
|
||||||
|
|
||||||
|
if (!*buffer)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
r = *buffer;
|
||||||
|
|
||||||
|
if (CheckBuffer((BufferObject *)(r)))
|
||||||
|
{
|
||||||
|
*buffer = NULL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!((BufferObject *)(r))->buf->b_next)
|
||||||
|
next = NULL;
|
||||||
|
else if (!(next = BufferNew(((BufferObject *)(r))->buf->b_next)))
|
||||||
|
return NULL;
|
||||||
|
*buffer = next;
|
||||||
|
/* Do not increment reference: we no longer hold it (decref), but whoever on
|
||||||
|
* other side will hold (incref). Decref+incref = nothing.
|
||||||
|
*/
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
BufMapIter(PyObject *self UNUSED)
|
||||||
|
{
|
||||||
|
PyObject *buffer;
|
||||||
|
|
||||||
|
buffer = BufferNew(firstbuf);
|
||||||
|
return IterNew(buffer,
|
||||||
|
(destructorfun) BufMapIterDestruct, (nextfun) BufMapIterNext);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyMappingMethods BufMapAsMapping = {
|
||||||
|
(lenfunc) BufMapLength,
|
||||||
|
(binaryfunc) BufMapItem,
|
||||||
|
(objobjargproc) 0,
|
||||||
|
};
|
||||||
|
|
||||||
/* Current items object
|
/* Current items object
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -3383,6 +3538,14 @@ init_structs(void)
|
|||||||
OutputType.tp_setattr = OutputSetattr;
|
OutputType.tp_setattr = OutputSetattr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
vim_memset(&IterType, 0, sizeof(IterType));
|
||||||
|
IterType.tp_name = "vim.iter";
|
||||||
|
IterType.tp_basicsize = sizeof(IterObject);
|
||||||
|
IterType.tp_flags = Py_TPFLAGS_DEFAULT;
|
||||||
|
IterType.tp_doc = "generic iterator object";
|
||||||
|
IterType.tp_iter = IterIter;
|
||||||
|
IterType.tp_iternext = IterNext;
|
||||||
|
|
||||||
vim_memset(&BufferType, 0, sizeof(BufferType));
|
vim_memset(&BufferType, 0, sizeof(BufferType));
|
||||||
BufferType.tp_name = "vim.buffer";
|
BufferType.tp_name = "vim.buffer";
|
||||||
BufferType.tp_basicsize = sizeof(BufferType);
|
BufferType.tp_basicsize = sizeof(BufferType);
|
||||||
@@ -3426,6 +3589,7 @@ init_structs(void)
|
|||||||
BufMapType.tp_basicsize = sizeof(BufMapObject);
|
BufMapType.tp_basicsize = sizeof(BufMapObject);
|
||||||
BufMapType.tp_as_mapping = &BufMapAsMapping;
|
BufMapType.tp_as_mapping = &BufMapAsMapping;
|
||||||
BufMapType.tp_flags = Py_TPFLAGS_DEFAULT;
|
BufMapType.tp_flags = Py_TPFLAGS_DEFAULT;
|
||||||
|
BufMapType.tp_iter = BufMapIter;
|
||||||
BufferType.tp_doc = "vim buffer list";
|
BufferType.tp_doc = "vim buffer list";
|
||||||
|
|
||||||
vim_memset(&WinListType, 0, sizeof(WinListType));
|
vim_memset(&WinListType, 0, sizeof(WinListType));
|
||||||
@@ -3492,6 +3656,7 @@ init_structs(void)
|
|||||||
ListType.tp_flags = Py_TPFLAGS_DEFAULT;
|
ListType.tp_flags = Py_TPFLAGS_DEFAULT;
|
||||||
ListType.tp_doc = "list pushing modifications to vim structure";
|
ListType.tp_doc = "list pushing modifications to vim structure";
|
||||||
ListType.tp_methods = ListMethods;
|
ListType.tp_methods = ListMethods;
|
||||||
|
ListType.tp_iter = ListIter;
|
||||||
#if PY_MAJOR_VERSION >= 3
|
#if PY_MAJOR_VERSION >= 3
|
||||||
ListType.tp_getattro = ListGetattro;
|
ListType.tp_getattro = ListGetattro;
|
||||||
ListType.tp_setattro = ListSetattro;
|
ListType.tp_setattro = ListSetattro;
|
||||||
@@ -3501,7 +3666,7 @@ init_structs(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
vim_memset(&FunctionType, 0, sizeof(FunctionType));
|
vim_memset(&FunctionType, 0, sizeof(FunctionType));
|
||||||
FunctionType.tp_name = "vim.list";
|
FunctionType.tp_name = "vim.function";
|
||||||
FunctionType.tp_basicsize = sizeof(FunctionObject);
|
FunctionType.tp_basicsize = sizeof(FunctionObject);
|
||||||
FunctionType.tp_dealloc = FunctionDestructor;
|
FunctionType.tp_dealloc = FunctionDestructor;
|
||||||
FunctionType.tp_call = FunctionCall;
|
FunctionType.tp_call = FunctionCall;
|
||||||
|
@@ -1219,6 +1219,7 @@ PythonMod_Init(void)
|
|||||||
static char *(argv[2]) = {"/must>not&exist/foo", NULL};
|
static char *(argv[2]) = {"/must>not&exist/foo", NULL};
|
||||||
|
|
||||||
/* Fixups... */
|
/* Fixups... */
|
||||||
|
PyType_Ready(&IterType);
|
||||||
PyType_Ready(&BufferType);
|
PyType_Ready(&BufferType);
|
||||||
PyType_Ready(&RangeType);
|
PyType_Ready(&RangeType);
|
||||||
PyType_Ready(&WindowType);
|
PyType_Ready(&WindowType);
|
||||||
|
@@ -1519,6 +1519,7 @@ Py3Init_vim(void)
|
|||||||
/* The special value is removed from sys.path in Python3_Init(). */
|
/* The special value is removed from sys.path in Python3_Init(). */
|
||||||
static wchar_t *(argv[2]) = {L"/must>not&exist/foo", NULL};
|
static wchar_t *(argv[2]) = {L"/must>not&exist/foo", NULL};
|
||||||
|
|
||||||
|
PyType_Ready(&IterType);
|
||||||
PyType_Ready(&BufferType);
|
PyType_Ready(&BufferType);
|
||||||
PyType_Ready(&RangeType);
|
PyType_Ready(&RangeType);
|
||||||
PyType_Ready(&WindowType);
|
PyType_Ready(&WindowType);
|
||||||
|
@@ -127,4 +127,6 @@ int modify_fname __ARGS((char_u *src, int *usedlen, char_u **fnamep, char_u **bu
|
|||||||
char_u *do_string_sub __ARGS((char_u *str, char_u *pat, char_u *sub, char_u *flags));
|
char_u *do_string_sub __ARGS((char_u *str, char_u *pat, char_u *sub, char_u *flags));
|
||||||
int switch_win __ARGS((win_T **, tabpage_T **, win_T *, tabpage_T *));
|
int switch_win __ARGS((win_T **, tabpage_T **, win_T *, tabpage_T *));
|
||||||
void restore_win __ARGS((win_T *, tabpage_T *));
|
void restore_win __ARGS((win_T *, tabpage_T *));
|
||||||
|
void list_add_watch __ARGS((list_T *l, listwatch_T *lw));
|
||||||
|
void list_rem_watch __ARGS((list_T *l, listwatch_T *lwrem));
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
@@ -477,6 +477,9 @@ EOF
|
|||||||
: call RecVars(oname)
|
: call RecVars(oname)
|
||||||
:endfor
|
:endfor
|
||||||
:only
|
:only
|
||||||
|
:for buf in g:bufs[1:]
|
||||||
|
: execute 'bwipeout!' buf
|
||||||
|
:endfor
|
||||||
:"
|
:"
|
||||||
:" Test buffer object
|
:" Test buffer object
|
||||||
:vnew
|
:vnew
|
||||||
@@ -519,6 +522,62 @@ for expr in ('b[1]','b[:] = ["A", "B"]','b[:]','b.append("abc")'):
|
|||||||
# Should not happen in any case
|
# Should not happen in any case
|
||||||
cb.append('No exception for ' + expr)
|
cb.append('No exception for ' + expr)
|
||||||
EOF
|
EOF
|
||||||
|
:"
|
||||||
|
:" Test vim.buffers object
|
||||||
|
:set hidden
|
||||||
|
:edit a
|
||||||
|
:buffer #
|
||||||
|
:edit b
|
||||||
|
:buffer #
|
||||||
|
:edit c
|
||||||
|
:buffer #
|
||||||
|
py << EOF
|
||||||
|
# Check GCing iterator that was not fully exhausted
|
||||||
|
i = iter(vim.buffers)
|
||||||
|
cb.append('i:' + str(next(i)))
|
||||||
|
# and also check creating more then one iterator at a time
|
||||||
|
i2 = iter(vim.buffers)
|
||||||
|
cb.append('i2:' + str(next(i2)))
|
||||||
|
cb.append('i:' + str(next(i)))
|
||||||
|
# The following should trigger GC and not cause any problems
|
||||||
|
del i
|
||||||
|
del i2
|
||||||
|
i3 = iter(vim.buffers)
|
||||||
|
cb.append('i3:' + str(next(i3)))
|
||||||
|
del i3
|
||||||
|
|
||||||
|
prevnum = 0
|
||||||
|
for b in vim.buffers:
|
||||||
|
# Check buffer order
|
||||||
|
if prevnum >= b.number:
|
||||||
|
cb.append('!!! Buffer numbers not in strictly ascending order')
|
||||||
|
# Check indexing: vim.buffers[number].number == number
|
||||||
|
cb.append(str(b.number) + ':' + repr(vim.buffers[b.number]) + '=' + repr(b))
|
||||||
|
prevnum = b.number
|
||||||
|
|
||||||
|
cb.append(str(len(vim.buffers)))
|
||||||
|
|
||||||
|
bnums = list(map(lambda b: b.number, vim.buffers))[1:]
|
||||||
|
|
||||||
|
# Test wiping out buffer with existing iterator
|
||||||
|
i4 = iter(vim.buffers)
|
||||||
|
cb.append('i4:' + str(next(i4)))
|
||||||
|
vim.command('bwipeout! ' + str(bnums.pop(0)))
|
||||||
|
try:
|
||||||
|
next(i4)
|
||||||
|
except vim.error:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
cb.append('!!!! No vim.error')
|
||||||
|
i4 = iter(vim.buffers)
|
||||||
|
vim.command('bwipeout! ' + str(bnums.pop(-1)))
|
||||||
|
vim.command('bwipeout! ' + str(bnums.pop(-1)))
|
||||||
|
cb.append('i4:' + str(next(i4)))
|
||||||
|
try:
|
||||||
|
next(i4)
|
||||||
|
except StopIteration:
|
||||||
|
cb.append('StopIteration')
|
||||||
|
EOF
|
||||||
:endfun
|
:endfun
|
||||||
:"
|
:"
|
||||||
:call Test()
|
:call Test()
|
||||||
|
@@ -319,3 +319,15 @@ bar
|
|||||||
Second line
|
Second line
|
||||||
Third line
|
Third line
|
||||||
foo
|
foo
|
||||||
|
i:<buffer test86.in>
|
||||||
|
i2:<buffer test86.in>
|
||||||
|
i:<buffer a>
|
||||||
|
i3:<buffer test86.in>
|
||||||
|
1:<buffer test86.in>=<buffer test86.in>
|
||||||
|
6:<buffer a>=<buffer a>
|
||||||
|
7:<buffer b>=<buffer b>
|
||||||
|
8:<buffer c>=<buffer c>
|
||||||
|
4
|
||||||
|
i4:<buffer test86.in>
|
||||||
|
i4:<buffer test86.in>
|
||||||
|
StopIteration
|
||||||
|
@@ -446,6 +446,9 @@ EOF
|
|||||||
: call RecVars(oname)
|
: call RecVars(oname)
|
||||||
:endfor
|
:endfor
|
||||||
:only
|
:only
|
||||||
|
:for buf in g:bufs[1:]
|
||||||
|
: execute 'bwipeout!' buf
|
||||||
|
:endfor
|
||||||
:"
|
:"
|
||||||
:" Test buffer object
|
:" Test buffer object
|
||||||
:vnew
|
:vnew
|
||||||
@@ -488,6 +491,62 @@ for expr in ('b[1]','b[:] = ["A", "B"]','b[:]','b.append("abc")'):
|
|||||||
# Should not happen in any case
|
# Should not happen in any case
|
||||||
cb.append('No exception for ' + expr)
|
cb.append('No exception for ' + expr)
|
||||||
EOF
|
EOF
|
||||||
|
:"
|
||||||
|
:" Test vim.buffers object
|
||||||
|
:set hidden
|
||||||
|
:edit a
|
||||||
|
:buffer #
|
||||||
|
:edit b
|
||||||
|
:buffer #
|
||||||
|
:edit c
|
||||||
|
:buffer #
|
||||||
|
py3 << EOF
|
||||||
|
# Check GCing iterator that was not fully exhausted
|
||||||
|
i = iter(vim.buffers)
|
||||||
|
cb.append('i:' + str(next(i)))
|
||||||
|
# and also check creating more then one iterator at a time
|
||||||
|
i2 = iter(vim.buffers)
|
||||||
|
cb.append('i2:' + str(next(i2)))
|
||||||
|
cb.append('i:' + str(next(i)))
|
||||||
|
# The following should trigger GC and not cause any problems
|
||||||
|
del i
|
||||||
|
del i2
|
||||||
|
i3 = iter(vim.buffers)
|
||||||
|
cb.append('i3:' + str(next(i3)))
|
||||||
|
del i3
|
||||||
|
|
||||||
|
prevnum = 0
|
||||||
|
for b in vim.buffers:
|
||||||
|
# Check buffer order
|
||||||
|
if prevnum >= b.number:
|
||||||
|
cb.append('!!! Buffer numbers not in strictly ascending order')
|
||||||
|
# Check indexing: vim.buffers[number].number == number
|
||||||
|
cb.append(str(b.number) + ':' + repr(vim.buffers[b.number]) + '=' + repr(b))
|
||||||
|
prevnum = b.number
|
||||||
|
|
||||||
|
cb.append(str(len(vim.buffers)))
|
||||||
|
|
||||||
|
bnums = list(map(lambda b: b.number, vim.buffers))[1:]
|
||||||
|
|
||||||
|
# Test wiping out buffer with existing iterator
|
||||||
|
i4 = iter(vim.buffers)
|
||||||
|
cb.append('i4:' + str(next(i4)))
|
||||||
|
vim.command('bwipeout! ' + str(bnums.pop(0)))
|
||||||
|
try:
|
||||||
|
next(i4)
|
||||||
|
except vim.error:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
cb.append('!!!! No vim.error')
|
||||||
|
i4 = iter(vim.buffers)
|
||||||
|
vim.command('bwipeout! ' + str(bnums.pop(-1)))
|
||||||
|
vim.command('bwipeout! ' + str(bnums.pop(-1)))
|
||||||
|
cb.append('i4:' + str(next(i4)))
|
||||||
|
try:
|
||||||
|
next(i4)
|
||||||
|
except StopIteration:
|
||||||
|
cb.append('StopIteration')
|
||||||
|
EOF
|
||||||
:endfun
|
:endfun
|
||||||
:"
|
:"
|
||||||
:call Test()
|
:call Test()
|
||||||
@@ -496,6 +555,7 @@ EOF
|
|||||||
:call garbagecollect(1)
|
:call garbagecollect(1)
|
||||||
:"
|
:"
|
||||||
:/^start:/,$wq! test.out
|
:/^start:/,$wq! test.out
|
||||||
|
:call getchar()
|
||||||
ENDTEST
|
ENDTEST
|
||||||
|
|
||||||
start:
|
start:
|
||||||
|
@@ -308,3 +308,15 @@ bar
|
|||||||
Second line
|
Second line
|
||||||
Third line
|
Third line
|
||||||
foo
|
foo
|
||||||
|
i:<buffer test87.in>
|
||||||
|
i2:<buffer test87.in>
|
||||||
|
i:<buffer a>
|
||||||
|
i3:<buffer test87.in>
|
||||||
|
1:<buffer test87.in>=<buffer test87.in>
|
||||||
|
6:<buffer a>=<buffer a>
|
||||||
|
7:<buffer b>=<buffer b>
|
||||||
|
8:<buffer c>=<buffer c>
|
||||||
|
4
|
||||||
|
i4:<buffer test87.in>
|
||||||
|
i4:<buffer test87.in>
|
||||||
|
StopIteration
|
||||||
|
@@ -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 */
|
||||||
|
/**/
|
||||||
|
947,
|
||||||
/**/
|
/**/
|
||||||
946,
|
946,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user