0
0
mirror of https://github.com/vim/vim.git synced 2025-08-27 20:13:38 -04:00

updated for version 7.3.949

Problem:    Python: no easy access to tabpages.
Solution:   Add vim.tabpages and vim.current.tabpage. (ZyX)
This commit is contained in:
Bram Moolenaar 2013-05-15 15:12:29 +02:00
parent 03db85b398
commit 5e538ecd5e
10 changed files with 426 additions and 13 deletions

View File

@ -223,6 +223,20 @@ vim.windows *python-windows*
:py w in vim.windows # Membership test
:py n = len(vim.windows) # Number of elements
:py for w in vim.windows: # Sequential access
< Note: vim.windows object always accesses current tab page,.
|python-tabpage|.windows objects are bound to parent |python-tabpage|
object and always use windows from that tab page (or throw vim.error
in case tab page was deleted). You can keep a reference to both
without keeping a reference to vim module object or |python-tabpage|,
they will not loose their properties in this case.
vim.tabpages *python-tabpages*
A sequence object providing access to the list of vim tab pages. The
object supports the following operations: >
:py t = vim.tabpages[i] # Indexing (read-only)
:py t in vim.tabpages # Membership test
:py n = len(vim.tabpages) # Number of elements
:py for t in vim.tabpages: # Sequential access
<
vim.current *python-current*
An object providing access (via specific attributes) to various
@ -230,6 +244,7 @@ vim.current *python-current*
vim.current.line The current line (RW) String
vim.current.buffer The current buffer (RO) Buffer
vim.current.window The current window (RO) Window
vim.current.tabpage The current tab page (RO) TabPage
vim.current.range The current line range (RO) Range
The last case deserves a little explanation. When the :python or
@ -375,6 +390,8 @@ Example (assume r is the current range):
Window objects represent vim windows. You can obtain them in a number of ways:
- via vim.current.window (|python-current|)
- from indexing vim.windows (|python-windows|)
- from indexing "windows" attribute of a tab page (|python-tabpage|)
- from the "window" attribute of a tab page (|python-tabpage|)
You can manipulate window objects only through their attributes. They have no
methods, and no sequence or other interface.
@ -406,6 +423,24 @@ Window attributes are:
The height attribute is writable only if the screen is split horizontally.
The width attribute is writable only if the screen is split vertically.
==============================================================================
6. Tab page objects *python-tabpage*
Tab page objects represent vim tab pages. You can obtain them in a number of
ways:
- via vim.current.tabpage (|python-current|)
- from indexing vim.tabpages (|python-tabpages|)
You can use this object to access tab page windows. They have no methods and
no sequence or other interfaces.
Tab page attributes are:
number The tab page number like the one returned by
|tabpagenr()|.
windows Like |python-windows|, but for current tab page.
vars The tab page |t:| variables.
window Current tabpage window.
==============================================================================
6. pyeval() and py3eval() Vim functions *python-pyeval*

View File

@ -27,6 +27,7 @@ typedef int Py_ssize_t; /* Python 2.4 and earlier don't have this type. */
#define INVALID_BUFFER_VALUE ((buf_T *)(-1))
#define INVALID_WINDOW_VALUE ((win_T *)(-1))
#define INVALID_TABPAGE_VALUE ((tabpage_T *)(-1))
static int ConvertFromPyObject(PyObject *, typval_T *);
static int _ConvertFromPyObject(PyObject *, typval_T *, PyObject *);
@ -1579,6 +1580,155 @@ static PyMappingMethods OptionsAsMapping = {
(objobjargproc) OptionsAssItem,
};
/* Tabpage object
*/
typedef struct
{
PyObject_HEAD
tabpage_T *tab;
} TabPageObject;
static PyObject *WinListNew(TabPageObject *tabObject);
static PyTypeObject TabPageType;
static int
CheckTabPage(TabPageObject *this)
{
if (this->tab == INVALID_TABPAGE_VALUE)
{
PyErr_SetVim(_("attempt to refer to deleted tab page"));
return -1;
}
return 0;
}
static PyObject *
TabPageNew(tabpage_T *tab)
{
TabPageObject *self;
if (TAB_PYTHON_REF(tab))
{
self = TAB_PYTHON_REF(tab);
Py_INCREF(self);
}
else
{
self = PyObject_NEW(TabPageObject, &TabPageType);
if (self == NULL)
return NULL;
self->tab = tab;
TAB_PYTHON_REF(tab) = self;
}
return (PyObject *)(self);
}
static void
TabPageDestructor(PyObject *self)
{
TabPageObject *this = (TabPageObject *)(self);
if (this->tab && this->tab != INVALID_TABPAGE_VALUE)
TAB_PYTHON_REF(this->tab) = NULL;
DESTRUCTOR_FINISH(self);
}
static PyObject *
TabPageAttr(TabPageObject *this, char *name)
{
if (strcmp(name, "windows") == 0)
return WinListNew(this);
else if (strcmp(name, "number") == 0)
return PyLong_FromLong((long) get_tab_number(this->tab));
else if (strcmp(name, "vars") == 0)
return DictionaryNew(this->tab->tp_vars);
else if (strcmp(name, "window") == 0)
{
/* For current tab window.c does not bother to set or update tp_curwin
*/
if (this->tab == curtab)
return WindowNew(curwin);
else
return WindowNew(this->tab->tp_curwin);
}
return NULL;
}
static PyObject *
TabPageRepr(PyObject *self)
{
static char repr[100];
TabPageObject *this = (TabPageObject *)(self);
if (this->tab == INVALID_TABPAGE_VALUE)
{
vim_snprintf(repr, 100, _("<tabpage object (deleted) at %p>"), (self));
return PyString_FromString(repr);
}
else
{
int t = get_tab_number(this->tab);
if (t == 0)
vim_snprintf(repr, 100, _("<tabpage object (unknown) at %p>"),
(self));
else
vim_snprintf(repr, 100, _("<tabpage %d>"), t - 1);
return PyString_FromString(repr);
}
}
static struct PyMethodDef TabPageMethods[] = {
/* name, function, calling, documentation */
{ NULL, NULL, 0, NULL }
};
/*
* Window list object
*/
static PyTypeObject TabListType;
static PySequenceMethods TabListAsSeq;
typedef struct
{
PyObject_HEAD
} TabListObject;
static PyInt
TabListLength(PyObject *self UNUSED)
{
tabpage_T *tp = first_tabpage;
PyInt n = 0;
while (tp != NULL)
{
++n;
tp = tp->tp_next;
}
return n;
}
static PyObject *
TabListItem(PyObject *self UNUSED, PyInt n)
{
tabpage_T *tp;
for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, --n)
if (n == 0)
return TabPageNew(tp);
PyErr_SetString(PyExc_IndexError, _("no such tab page"));
return NULL;
}
/* Window object
*/
@ -1588,8 +1738,6 @@ typedef struct
win_T *win;
} WindowObject;
static int WindowSetattr(PyObject *, char *, PyObject *);
static PyObject *WindowRepr(PyObject *);
static PyTypeObject WindowType;
static int
@ -1681,7 +1829,7 @@ WindowAttr(WindowObject *this, char *name)
return OptionsNew(SREQ_WIN, this->win, (checkfun) CheckWindow,
(PyObject *) this);
else if (strcmp(name, "number") == 0)
return PyLong_FromLong((long) get_win_number(this->win));
return PyLong_FromLong((long) get_win_number(this->win, firstwin));
else if (strcmp(name,"__members__") == 0)
return Py_BuildValue("[ssssssss]", "buffer", "cursor", "height", "vars",
"options", "number", "row", "col");
@ -1797,7 +1945,7 @@ WindowRepr(PyObject *self)
}
else
{
int w = get_win_number(this->win);
int w = get_win_number(this->win, firstwin);
if (w == 0)
vim_snprintf(repr, 100, _("<window object (unknown) at %p>"),
@ -1824,14 +1972,59 @@ static PySequenceMethods WinListAsSeq;
typedef struct
{
PyObject_HEAD
TabPageObject *tabObject;
} WinListObject;
static PyInt
WinListLength(PyObject *self UNUSED)
static PyObject *
WinListNew(TabPageObject *tabObject)
{
win_T *w = firstwin;
WinListObject *self;
self = PyObject_NEW(WinListObject, &WinListType);
self->tabObject = tabObject;
Py_INCREF(tabObject);
return (PyObject *)(self);
}
static void
WinListDestructor(PyObject *self)
{
TabPageObject *tabObject = ((WinListObject *)(self))->tabObject;
if (tabObject)
Py_DECREF((PyObject *)(tabObject));
DESTRUCTOR_FINISH(self);
}
static win_T *
get_firstwin(WinListObject *this)
{
if (this->tabObject)
{
if (CheckTabPage(this->tabObject))
return NULL;
/* For current tab window.c does not bother to set or update tp_firstwin
*/
else if (this->tabObject->tab == curtab)
return firstwin;
else
return this->tabObject->tab->tp_firstwin;
}
else
return firstwin;
}
static PyInt
WinListLength(PyObject *self)
{
win_T *w;
PyInt n = 0;
if (!(w = get_firstwin((WinListObject *)(self))))
return -1;
while (w != NULL)
{
++n;
@ -1842,11 +2035,14 @@ WinListLength(PyObject *self UNUSED)
}
static PyObject *
WinListItem(PyObject *self UNUSED, PyInt n)
WinListItem(PyObject *self, PyInt n)
{
win_T *w;
for (w = firstwin; w != NULL; w = W_NEXT(w), --n)
if (!(w = get_firstwin((WinListObject *)(self))))
return NULL;
for (; w != NULL; w = W_NEXT(w), --n)
if (n == 0)
return WindowNew(w);
@ -3018,12 +3214,15 @@ CurrentGetattr(PyObject *self UNUSED, char *name)
return (PyObject *)BufferNew(curbuf);
else if (strcmp(name, "window") == 0)
return (PyObject *)WindowNew(curwin);
else if (strcmp(name, "tabpage") == 0)
return (PyObject *)TabPageNew(curtab);
else if (strcmp(name, "line") == 0)
return GetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum);
else if (strcmp(name, "range") == 0)
return RangeNew(curbuf, RangeStart, RangeEnd);
else if (strcmp(name,"__members__") == 0)
return Py_BuildValue("[ssss]", "buffer", "window", "line", "range");
return Py_BuildValue("[sssss]", "buffer", "window", "line", "range",
"tabpage");
else
{
PyErr_SetString(PyExc_AttributeError, name);
@ -3568,6 +3767,23 @@ init_structs(void)
WindowType.tp_setattr = WindowSetattr;
#endif
vim_memset(&TabPageType, 0, sizeof(TabPageType));
TabPageType.tp_name = "vim.tabpage";
TabPageType.tp_basicsize = sizeof(TabPageObject);
TabPageType.tp_dealloc = TabPageDestructor;
TabPageType.tp_repr = TabPageRepr;
TabPageType.tp_flags = Py_TPFLAGS_DEFAULT;
TabPageType.tp_doc = "vim tab page object";
TabPageType.tp_methods = TabPageMethods;
#if PY_MAJOR_VERSION >= 3
TabPageType.tp_getattro = TabPageGetattro;
TabPageType.tp_alloc = call_PyType_GenericAlloc;
TabPageType.tp_new = call_PyType_GenericNew;
TabPageType.tp_free = call_PyObject_Free;
#else
TabPageType.tp_getattr = TabPageGetattr;
#endif
vim_memset(&BufMapType, 0, sizeof(BufMapType));
BufMapType.tp_name = "vim.bufferlist";
BufMapType.tp_basicsize = sizeof(BufMapObject);
@ -3582,6 +3798,14 @@ init_structs(void)
WinListType.tp_as_sequence = &WinListAsSeq;
WinListType.tp_flags = Py_TPFLAGS_DEFAULT;
WinListType.tp_doc = "vim window list";
WinListType.tp_dealloc = WinListDestructor;
vim_memset(&TabListType, 0, sizeof(TabListType));
TabListType.tp_name = "vim.tabpagelist";
TabListType.tp_basicsize = sizeof(TabListType);
TabListType.tp_as_sequence = &TabListAsSeq;
TabListType.tp_flags = Py_TPFLAGS_DEFAULT;
TabListType.tp_doc = "vim tab page list";
vim_memset(&RangeType, 0, sizeof(RangeType));
RangeType.tp_name = "vim.range";

View File

@ -624,10 +624,12 @@ static int initialised = 0;
#define WIN_PYTHON_REF(win) win->w_python_ref
#define BUF_PYTHON_REF(buf) buf->b_python_ref
#define TAB_PYTHON_REF(tab) tab->tp_python_ref
static PyObject *OutputGetattr(PyObject *, char *);
static PyObject *BufferGetattr(PyObject *, char *);
static PyObject *WindowGetattr(PyObject *, char *);
static PyObject *TabPageGetattr(PyObject *, char *);
static PyObject *RangeGetattr(PyObject *, char *);
static PyObject *DictionaryGetattr(PyObject *, char*);
static PyObject *ListGetattr(PyObject *, char *);
@ -1137,6 +1139,24 @@ RangeAssSlice(PyObject *self, PyInt lo, PyInt hi, PyObject *val)
&((RangeObject *)(self))->end);
}
/* TabPage object - Implementation
*/
static PyObject *
TabPageGetattr(PyObject *self, char *name)
{
PyObject *r;
if (CheckTabPage((TabPageObject *)(self)))
return NULL;
r = TabPageAttr((TabPageObject *)(self), name);
if (r || PyErr_Occurred())
return r;
else
return Py_FindMethod(TabPageMethods, self, name);
}
/* Window object - Implementation
*/
@ -1155,6 +1175,24 @@ WindowGetattr(PyObject *self, char *name)
return Py_FindMethod(WindowMethods, self, name);
}
/* Tab page list object - Definitions
*/
static PySequenceMethods TabListAsSeq = {
(PyInquiry) TabListLength, /* sq_length, len(x) */
(binaryfunc) 0, /* sq_concat, x+y */
(PyIntArgFunc) 0, /* sq_repeat, x*n */
(PyIntArgFunc) TabListItem, /* sq_item, x[i] */
(PyIntIntArgFunc) 0, /* sq_slice, x[i:j] */
(PyIntObjArgProc) 0, /* sq_ass_item, x[i]=v */
(PyIntIntObjArgProc) 0, /* sq_ass_slice, x[i:j]=v */
(objobjproc) 0,
#if PY_MAJOR_VERSION >= 2
(binaryfunc) 0,
0,
#endif
};
/* Window list object - Definitions
*/
@ -1198,6 +1236,17 @@ python_window_free(win_T *win)
WIN_PYTHON_REF(win) = NULL;
}
}
void
python_tabpage_free(tabpage_T *tab)
{
if (TAB_PYTHON_REF(tab) != NULL)
{
TabPageObject *tp = TAB_PYTHON_REF(tab);
tp->tab = INVALID_TABPAGE_VALUE;
TAB_PYTHON_REF(tab) = NULL;
}
}
#endif
static BufMapObject TheBufferMap =
@ -1208,6 +1257,7 @@ static BufMapObject TheBufferMap =
static WinListObject TheWindowList =
{
PyObject_HEAD_INIT(&WinListType)
NULL
};
static CurrentObject TheCurrent =
@ -1215,6 +1265,11 @@ static CurrentObject TheCurrent =
PyObject_HEAD_INIT(&CurrentType)
};
static TabListObject TheTabPageList =
{
PyObject_HEAD_INIT(&TabListType)
};
static int
PythonMod_Init(void)
{
@ -1229,8 +1284,10 @@ PythonMod_Init(void)
PyType_Ready(&BufferType);
PyType_Ready(&RangeType);
PyType_Ready(&WindowType);
PyType_Ready(&TabPageType);
PyType_Ready(&BufMapType);
PyType_Ready(&WinListType);
PyType_Ready(&TabListType);
PyType_Ready(&CurrentType);
PyType_Ready(&OptionsType);
@ -1246,6 +1303,7 @@ PythonMod_Init(void)
PyDict_SetItemString(dict, "buffers", (PyObject *)(void *)&TheBufferMap);
PyDict_SetItemString(dict, "current", (PyObject *)(void *)&TheCurrent);
PyDict_SetItemString(dict, "windows", (PyObject *)(void *)&TheWindowList);
PyDict_SetItemString(dict, "tabpages", (PyObject *)(void *)&TheTabPageList);
tmp = DictionaryNew(&globvardict);
PyDict_SetItemString(dict, "vars", tmp);
Py_DECREF(tmp);

View File

@ -626,6 +626,7 @@ static int py3initialised = 0;
#define WIN_PYTHON_REF(win) win->w_python3_ref
#define BUF_PYTHON_REF(buf) buf->b_python3_ref
#define TAB_PYTHON_REF(tab) tab->tp_python3_ref
static void
call_PyObject_Free(void *p)
@ -652,6 +653,7 @@ call_PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems)
static PyObject *OutputGetattro(PyObject *, PyObject *);
static int OutputSetattro(PyObject *, PyObject *, PyObject *);
static PyObject *BufferGetattro(PyObject *, PyObject *);
static PyObject *TabPageGetattro(PyObject *, PyObject *);
static PyObject *WindowGetattro(PyObject *, PyObject *);
static int WindowSetattro(PyObject *, PyObject *, PyObject *);
static PyObject *RangeGetattro(PyObject *, PyObject *);
@ -1275,6 +1277,26 @@ RangeAsSubscript(PyObject *self, PyObject *idx, PyObject *val)
}
}
/* TabPage object - Implementation
*/
static PyObject *
TabPageGetattro(PyObject *self, PyObject *nameobj)
{
PyObject *r;
GET_ATTR_STRING(name, nameobj);
if (CheckTabPage((TabPageObject *)(self)))
return NULL;
r = TabPageAttr((TabPageObject *)(self), name);
if (r || PyErr_Occurred())
return r;
else
return PyObject_GenericGetAttr(self, nameobj);
}
/* Window object - Implementation
*/
@ -1303,6 +1325,22 @@ WindowSetattro(PyObject *self, PyObject *nameobj, PyObject *val)
return WindowSetattr(self, name, val);
}
/* Tab page list object - Definitions
*/
static PySequenceMethods TabListAsSeq = {
(lenfunc) TabListLength, /* sq_length, len(x) */
(binaryfunc) 0, /* sq_concat, x+y */
(ssizeargfunc) 0, /* sq_repeat, x*n */
(ssizeargfunc) TabListItem, /* sq_item, x[i] */
0, /* sq_slice, x[i:j] */
(ssizeobjargproc)0, /* sq_as_item, x[i]=v */
0, /* sq_ass_slice, x[i:j]=v */
0, /* sq_contains */
0, /* sq_inplace_concat */
0, /* sq_inplace_repeat */
};
/* Window list object - Definitions
*/
@ -1497,6 +1535,17 @@ python3_window_free(win_T *win)
WIN_PYTHON_REF(win) = NULL;
}
}
void
python3_tabpage_free(tabpage_T *tab)
{
if (TAB_PYTHON_REF(tab) != NULL)
{
TabPageObject *tp = TAB_PYTHON_REF(tab);
tp->tab = INVALID_TABPAGE_VALUE;
TAB_PYTHON_REF(tab) = NULL;
}
}
#endif
static BufMapObject TheBufferMap =
@ -1507,6 +1556,7 @@ static BufMapObject TheBufferMap =
static WinListObject TheWindowList =
{
PyObject_HEAD_INIT(&WinListType)
NULL
};
static CurrentObject TheCurrent =
@ -1514,6 +1564,11 @@ static CurrentObject TheCurrent =
PyObject_HEAD_INIT(&CurrentType)
};
static TabListObject TheTabPageList =
{
PyObject_HEAD_INIT(&TabListType)
};
static PyObject *
Py3Init_vim(void)
{
@ -1526,8 +1581,10 @@ Py3Init_vim(void)
PyType_Ready(&BufferType);
PyType_Ready(&RangeType);
PyType_Ready(&WindowType);
PyType_Ready(&TabPageType);
PyType_Ready(&BufMapType);
PyType_Ready(&WinListType);
PyType_Ready(&TabListType);
PyType_Ready(&CurrentType);
PyType_Ready(&DictionaryType);
PyType_Ready(&ListType);
@ -1551,6 +1608,8 @@ Py3Init_vim(void)
PyModule_AddObject(mod, "current", (PyObject *)(void *)&TheCurrent);
Py_INCREF((PyObject *)(void *)&TheWindowList);
PyModule_AddObject(mod, "windows", (PyObject *)(void *)&TheWindowList);
Py_INCREF((PyObject *)(void *)&TheTabPageList);
PyModule_AddObject(mod, "tabpages", (PyObject *)(void *)&TheTabPageList);
PyModule_AddObject(mod, "vars", DictionaryNew(&globvardict));
PyModule_AddObject(mod, "vvars", DictionaryNew(&vimvardict));

View File

@ -6,6 +6,7 @@ void ex_python __ARGS((exarg_T *eap));
void ex_pyfile __ARGS((exarg_T *eap));
void python_buffer_free __ARGS((buf_T *buf));
void python_window_free __ARGS((win_T *win));
void python_tabpage_free __ARGS((tabpage_T *tab));
void do_pyeval __ARGS((char_u *str, typval_T *rettv));
void set_ref_in_python __ARGS((int copyID));
/* vim: set ft=c : */

View File

@ -6,6 +6,7 @@ void ex_py3 __ARGS((exarg_T *eap));
void ex_py3file __ARGS((exarg_T *eap));
void python3_buffer_free __ARGS((buf_T *buf));
void python3_window_free __ARGS((win_T *win));
void python3_tabpage_free __ARGS((tabpage_T *tab));
void do_py3eval __ARGS((char_u *str, typval_T *rettv));
void set_ref_in_python3 __ARGS((int copyID));
/* vim: set ft=c : */

View File

@ -74,5 +74,6 @@ int match_add __ARGS((win_T *wp, char_u *grp, char_u *pat, int prio, int id));
int match_delete __ARGS((win_T *wp, int id, int perr));
void clear_matches __ARGS((win_T *wp));
matchitem_T *get_match __ARGS((win_T *wp, int id));
int get_win_number __ARGS((win_T *wp));
int get_win_number __ARGS((win_T *wp, win_T *first_win));
int get_tab_number __ARGS((tabpage_T *tp));
/* vim: set ft=c : */

View File

@ -1759,6 +1759,14 @@ struct tabpage_S
dictitem_T tp_winvar; /* variable for "t:" Dictionary */
dict_T *tp_vars; /* internal variables, local to tab page */
#endif
#ifdef FEAT_PYTHON
void *tp_python_ref; /* The Python value for this tab page */
#endif
#ifdef FEAT_PYTHON3
void *tp_python3_ref; /* The Python value for this tab page */
#endif
};
/*

View File

@ -728,6 +728,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
949,
/**/
948,
/**/

View File

@ -3510,6 +3510,15 @@ free_tabpage(tp)
hash_init(&tp->tp_vars->dv_hashtab);
unref_var_dict(tp->tp_vars);
#endif
#ifdef FEAT_PYTHON
python_tabpage_free(tp);
#endif
#ifdef FEAT_PYTHON3
python3_tabpage_free(tp);
#endif
vim_free(tp);
}
@ -6734,12 +6743,12 @@ get_match(wp, id)
#if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) || defined(PROTO)
int
get_win_number(win_T *wp)
get_win_number(win_T *wp, win_T *first_win)
{
int i = 1;
win_T *w;
for (w = firstwin; w != NULL && w != wp; w = W_NEXT(w))
for (w = first_win; w != NULL && w != wp; w = W_NEXT(w))
++i;
if (w == NULL)
@ -6747,4 +6756,19 @@ get_win_number(win_T *wp)
else
return i;
}
int
get_tab_number(tabpage_T *tp)
{
int i = 1;
tabpage_T *t;
for (t = first_tabpage; t != NULL && t != tp; t = t->tp_next)
++i;
if (t == NULL)
return 0;
else
return i;
}
#endif