Hi all,

This patch implements the getbufinfo(), gettabinfo() and getwininfo()
functions. I have updated the patch to the latest Vim and also added
a test.

- Yegappan

On Tue, May 28, 2013 at 9:28 PM, Yegappan Lakshmanan
<[email protected]> wrote:
> Hi,
>
> On Sun, May 19, 2013 at 4:22 PM, Yegappan Lakshmanan
> <[email protected]> wrote:
>> Hi all,
>>
>>>>
>>>>> The attached patch introduces a new bufferlist() function which
>>>>> returns a List of buffers. Each list item is a dictionary containing
>>>>> the buffer attributes.  This function will be useful for plugin
>>>>> developers. The patch is
>>>>> against 7.3.905.
>>>>>
>>>>> We can extend this function in the future to return more information about
>>>>> the buffers.
>>>>
>>>> Thanks, I'll add it in the todo list.
>>>>
>>> I have added two more functions: winlist() and tabpagelist(). The updated
>>> diff is attached.
>>>
>>
>> I have added the buffer/window/tabpage local variables to the returned list.
>> The updated diff is attached.
>>
>
> I have updated the functions to also return buffer/window/tabpage options.
> The functions are renamed to bufinfo(), wininfo() and tabpageinfo().
> The functions
> can also be used to query information about a single buffer/window/tabpage.
>
> - Yegappan

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index b0b8479..2bb07a2 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1909,6 +1909,7 @@ function({name} [, {arglist}] [, {dict}])
 garbagecollect( [{atexit}])    none    free memory, breaking cyclic references
 get( {list}, {idx} [, {def}])  any     get item {idx} from {list} or {def}
 get( {dict}, {key} [, {def}])  any     get item {key} from {dict} or {def}
+getbufinfo( [{expr}])          List/Dict  list of buffers
 getbufline( {expr}, {lnum} [, {end}])
                                List    lines {lnum} to {end} of buffer {expr}
 getbufvar( {expr}, {varname} [, {def}])
@@ -1937,10 +1938,13 @@ getqflist()                     List    list of 
quickfix items
 getreg( [{regname} [, 1 [, {list}]]])
                                String or List   contents of register
 getregtype( [{regname}])       String  type of register
+gettabinfo( [{expr}])          List/Dict  list of tab pages
 gettabvar( {nr}, {varname} [, {def}])
                                any     variable {varname} in tab {nr} or {def}
 gettabwinvar( {tabnr}, {winnr}, {name} [, {def}])
                                any     {name} in {winnr} in tab page {tabnr}
+getwininfo( [{tpnr} [, {winnr}]])
+                               List/Dict  list of windows
 getwinposx()                   Number  X coord in pixels of GUI Vim window
 getwinposy()                   Number  Y coord in pixels of GUI Vim window
 getwinvar( {nr}, {varname} [, {def}])
@@ -3689,6 +3693,24 @@ get({dict}, {key} [, {default}])
                item is not available return {default}.  Return zero when
                {default} is omitted.
 
+getbufinfo([{expr}])                                   *getbufinfo()*
+               If {expr} is not specified, then information about all the
+               buffers is returned as a List. Each list item is a dictionary.
+               Otherwise, {expr} specifies a particular buffer to be used and
+               a Dict is returned.  For the use of {expr}, see |bufname()|
+               above.
+
+               Each list item is a dictionary with the following entries:
+                       changed         TRUE if the buffer is modified.
+                       changedtick     number of changes made to the buffer.
+                       hidden          TRUE if the buffer is hidden.
+                       lnum            current line number in buffer.
+                       loaded          TRUE if the buffer is loaded.
+                       name            full path to the file in the buffer.
+                       nr              buffer number.
+                       options         dictionary of buffer local options.
+                       variables       dictionary of buffer local variables.
+
                                                        *getbufline()*
 getbufline({expr}, {lnum} [, {end}])
                Return a |List| with the lines starting from {lnum} to {end}
@@ -4098,6 +4120,16 @@ getregtype([{regname}])                                  
*getregtype()*
                <CTRL-V> is one character with value 0x16.
                If {regname} is not specified, |v:register| is used.
 
+gettabinfo([{arg}])                                    *gettabinfo()*
+               If {arg} is not specified, then information about all the tab
+               pages is returned as a List. Each list item is a dictionary.
+               Otherwise, {arg} specifies the number of tab page to be used
+               and a Dict is returned.
+               Each list item is a dictionary with the following entries:
+                       nr              tab page number.
+                       numwindows      number of windows in the tab page.
+                       variables       dictionary of tabpage local variables.
+
 gettabvar({tabnr}, {varname} [, {def}])                                
*gettabvar()*
                Get the value of a tab-local variable {varname} in tab page
                {tabnr}. |t:var|
@@ -4138,6 +4170,24 @@ getwinposy()     The result is a Number, which is the Y 
coordinate in pixels of
                the top of the GUI Vim window.  The result will be -1 if the
                information is not available.
 
+getwininfo([{tpnr}, [{winnr}]])                                *getwininfo()*
+               Returns information about windows as a List or a Dict.
+               {tpnr} specifies the tab page number and {winnr} specifies the
+               window number. If both are supplied, then information about
+               the specified window is returned as a Dict. If {winnr} is not
+               supplied, then information about all the windows in {tpnr} is
+               returned as a List. If both are not supplied, then
+               information about all the windows in all the tab pages is
+               returned as a List.
+               Each list item is a dictionary with the following entries:
+                       nr              window number.
+                       tpnr            tab page number.
+                       height          window height.
+                       width           window width.
+                       bufnum          number of buffer in the window.
+                       options         dictionary of window local options.
+                       variables       dictionary of window local variables.
+
 getwinvar({winnr}, {varname} [, {def}])                                
*getwinvar()*
                Like |gettabwinvar()| for the current tabpage.
                Examples: >
diff --git a/src/eval.c b/src/eval.c
index 1c5a316..752cde0 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -460,6 +460,7 @@ static char_u *deref_func_name(char_u *name, int *lenp, 
partial_T **partial, int
 static int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, 
linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, partial_T 
*partial, dict_T *selfdict);
 static void emsg_funcname(char *ermsg, char_u *name);
 static int non_zero_arg(typval_T *argvars);
+static buf_T *get_buf_tv(typval_T *tv, int curtab_only);
 
 static void dict_free_contents(dict_T *d);
 static void dict_free_dict(dict_T *d);
@@ -581,6 +582,7 @@ static void f_foreground(typval_T *argvars, typval_T 
*rettv);
 static void f_function(typval_T *argvars, typval_T *rettv);
 static void f_garbagecollect(typval_T *argvars, typval_T *rettv);
 static void f_get(typval_T *argvars, typval_T *rettv);
+static void f_getbufinfo(typval_T *argvars, typval_T *rettv);
 static void f_getbufline(typval_T *argvars, typval_T *rettv);
 static void f_getbufvar(typval_T *argvars, typval_T *rettv);
 static void f_getchar(typval_T *argvars, typval_T *rettv);
@@ -604,8 +606,10 @@ static void f_getpos(typval_T *argvars, typval_T *rettv);
 static void f_getqflist(typval_T *argvars, typval_T *rettv);
 static void f_getreg(typval_T *argvars, typval_T *rettv);
 static void f_getregtype(typval_T *argvars, typval_T *rettv);
+static void f_gettabinfo(typval_T *argvars, typval_T *rettv);
 static void f_gettabvar(typval_T *argvars, typval_T *rettv);
 static void f_gettabwinvar(typval_T *argvars, typval_T *rettv);
+static void f_getwininfo(typval_T *argvars, typval_T *rettv);
 static void f_getwinposx(typval_T *argvars, typval_T *rettv);
 static void f_getwinposy(typval_T *argvars, typval_T *rettv);
 static void f_getwinvar(typval_T *argvars, typval_T *rettv);
@@ -916,6 +920,7 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, 
int *flagsp);
 static void setwinvar(typval_T *argvars, typval_T *rettv, int off);
 static int write_list(FILE *fd, list_T *list, int binary);
 static void get_cmd_output_as_rettv(typval_T *argvars, typval_T *rettv, int 
retlist);
+static int dict_add_dict(dict_T *d, char *key, dict_T *dict);
 
 
 #ifdef EBCDIC
@@ -7434,6 +7439,18 @@ rettv_dict_alloc(typval_T *rettv)
     return OK;
 }
 
+/*
+ * Set a dictionary as the return value
+ */
+    static void
+rettv_dict_set(typval_T *rettv, dict_T *d)
+{
+    if (d == NULL)
+       return;
+    rettv->v_type = VAR_DICT;
+    rettv->vval.v_dict = d;
+    ++d->dv_refcount;
+}
 
 /*
  * Unreference a Dictionary: decrement the reference count and free it when it
@@ -7701,6 +7718,30 @@ dict_add_list(dict_T *d, char *key, list_T *list)
 }
 
 /*
+ * Add a dict entry to dictionary "d".
+ * Returns FAIL when out of memory and when key already exists.
+ */
+    static int
+dict_add_dict(dict_T *d, char *key, dict_T *dict)
+{
+    dictitem_T *item;
+
+    item = dictitem_alloc((char_u *)key);
+    if (item == NULL)
+       return FAIL;
+    item->di_tv.v_lock = 0;
+    item->di_tv.v_type = VAR_DICT;
+    item->di_tv.vval.v_dict = dict;
+    if (dict_add(d, item) == FAIL)
+    {
+       dictitem_free(item);
+       return FAIL;
+    }
+    ++dict->dv_refcount;
+    return OK;
+}
+
+/*
  * Get the number of items in a Dictionary.
  */
     static long
@@ -8423,6 +8464,7 @@ static struct fst
     {"function",       1, 3, f_function},
     {"garbagecollect", 0, 1, f_garbagecollect},
     {"get",            2, 3, f_get},
+    {"getbufinfo",     0, 1, f_getbufinfo},
     {"getbufline",     2, 3, f_getbufline},
     {"getbufvar",      2, 3, f_getbufvar},
     {"getchar",                0, 1, f_getchar},
@@ -8447,8 +8489,10 @@ static struct fst
     {"getqflist",      0, 0, f_getqflist},
     {"getreg",         0, 3, f_getreg},
     {"getregtype",     0, 1, f_getregtype},
+    {"gettabinfo",     0, 1, f_gettabinfo},
     {"gettabvar",      2, 3, f_gettabvar},
     {"gettabwinvar",   3, 4, f_gettabwinvar},
+    {"getwininfo",     0, 2, f_getwininfo},
     {"getwinposx",     0, 0, f_getwinposx},
     {"getwinposy",     0, 0, f_getwinposy},
     {"getwinvar",      2, 3, f_getwinvar},
@@ -12359,6 +12403,236 @@ f_get(typval_T *argvars, typval_T *rettv)
        copy_tv(tv, rettv);
 }
 
+/*
+ * get_buffer_options
+ * Return all the buffer-local options in a dictionary.
+ */
+    static dict_T *
+get_buffer_options(buf_T *buf)
+{
+    dict_T     *opts;
+
+    /* Copy buffer options */
+    opts = dict_alloc();
+    if (opts == NULL)
+       return NULL;
+
+    dict_add_nr_str(opts, "autoindent", buf->b_p_ai, NULL);
+    dict_add_nr_str(opts, "backupcopy", 0L, buf->b_p_bkc);
+    dict_add_nr_str(opts, "copyindent", buf->b_p_ci, NULL);
+    dict_add_nr_str(opts, "binary", buf->b_p_bin, NULL);
+#ifdef FEAT_MBYTE
+    dict_add_nr_str(opts, "bomb", buf->b_p_bomb, NULL);
+#endif
+#ifdef FEAT_QUICKFIX
+    dict_add_nr_str(opts, "bufhidden", 0L, buf->b_p_bh);
+    dict_add_nr_str(opts, "buftype", 0L, buf->b_p_bt);
+#endif
+    dict_add_nr_str(opts, "buflisted", buf->b_p_bl, NULL);
+#ifdef FEAT_CINDENT
+    dict_add_nr_str(opts, "cindent", buf->b_p_cin, NULL);
+    dict_add_nr_str(opts, "cinoptions", 0L, buf->b_p_cino);
+    dict_add_nr_str(opts, "cinkeys", 0L, buf->b_p_cink);
+#endif
+#if defined(FEAT_CINDENT) || defined(FEAT_SMARTINDENT)
+    dict_add_nr_str(opts, "cinwords", 0L, buf->b_p_cinw);
+#endif
+#ifdef FEAT_COMMENTS
+    dict_add_nr_str(opts, "comments", 0L, buf->b_p_com);
+#endif
+#ifdef FEAT_FOLDING
+    dict_add_nr_str(opts, "commentstring", 0L, buf->b_p_cms);
+#endif
+#ifdef FEAT_INS_EXPAND
+    dict_add_nr_str(opts, "complete", 0L, buf->b_p_cpt);
+#endif
+#ifdef FEAT_COMPL_FUNC
+    dict_add_nr_str(opts, "completefunc", 0L, buf->b_p_cfu);
+    dict_add_nr_str(opts, "omnifunc", 0L, buf->b_p_ofu);
+#endif
+    dict_add_nr_str(opts, "endofline", buf->b_p_eol, NULL);
+    dict_add_nr_str(opts, "fixendofline", buf->b_p_fixeol, NULL);
+    dict_add_nr_str(opts, "expandtab", buf->b_p_et, NULL);
+#ifdef FEAT_MBYTE
+    dict_add_nr_str(opts, "fileencoding", 0L, buf->b_p_fenc);
+#endif
+    dict_add_nr_str(opts, "fileformat", 0L, buf->b_p_ff);
+#ifdef FEAT_AUTOCMD
+    dict_add_nr_str(opts, "filetype", 0L, buf->b_p_ft);
+#endif
+    dict_add_nr_str(opts, "formatoptions", 0L, buf->b_p_fo);
+    dict_add_nr_str(opts, "formatlistpat", 0L, buf->b_p_flp);
+    dict_add_nr_str(opts, "infercase", buf->b_p_inf, NULL);
+    dict_add_nr_str(opts, "iskeyword", 0L, buf->b_p_isk);
+#ifdef FEAT_FIND_ID
+    dict_add_nr_str(opts, "define", 0L, buf->b_p_def);
+    dict_add_nr_str(opts, "include", 0L, buf->b_p_inc);
+# ifdef FEAT_EVAL
+    dict_add_nr_str(opts, "includeexpr", 0L, buf->b_p_inex);
+# endif
+#endif
+#if defined(FEAT_CINDENT) && defined(FEAT_EVAL)
+    dict_add_nr_str(opts, "indentexpr", 0L, buf->b_p_inde);
+    dict_add_nr_str(opts, "indentkeys", 0L, buf->b_p_indk);
+#endif
+#ifdef FEAT_EVAL
+    dict_add_nr_str(opts, "formatexpr", 0L, buf->b_p_fex);
+#endif
+#ifdef FEAT_CRYPT
+    dict_add_nr_str(opts, "key", 0L, buf->b_p_key);
+#endif
+    dict_add_nr_str(opts, "keywordprg", 0L, buf->b_p_kp);
+#ifdef FEAT_LISP
+    dict_add_nr_str(opts, "lisp", buf->b_p_lisp, NULL);
+#endif
+    dict_add_nr_str(opts, "matchpairs", 0L, buf->b_p_mps);
+    dict_add_nr_str(opts, "modeline", buf->b_p_ml, NULL);
+    dict_add_nr_str(opts, "modifiable", buf->b_p_ma, NULL);
+    dict_add_nr_str(opts, "nrformats", 0L, buf->b_p_nf);
+    dict_add_nr_str(opts, "preserveindent", buf->b_p_pi, NULL);
+#ifdef FEAT_TEXTOBJ
+    dict_add_nr_str(opts, "quoteescape", 0L, buf->b_p_qe);
+#endif
+    dict_add_nr_str(opts, "readonly", buf->b_p_ro, NULL);
+    dict_add_nr_str(opts, "shiftwidth", buf->b_p_sw, NULL);
+#ifndef SHORT_FNAME
+    dict_add_nr_str(opts, "shortname", buf->b_p_sn, NULL);
+#endif
+#ifdef FEAT_SMARTINDENT
+    dict_add_nr_str(opts, "smartindent", buf->b_p_si, NULL);
+#endif
+    dict_add_nr_str(opts, "softtabstop", buf->b_p_sts, NULL);
+#ifdef FEAT_SEARCHPATH
+    dict_add_nr_str(opts, "suffixesadd", 0L, buf->b_p_sua);
+#endif
+    dict_add_nr_str(opts, "swapfile", buf->b_p_swf, NULL);
+#ifdef FEAT_SYN_HL
+    dict_add_nr_str(opts, "synmaxcol", buf->b_p_smc, NULL);
+    dict_add_nr_str(opts, "syntax", 0L, buf->b_p_syn);
+#endif
+    dict_add_nr_str(opts, "tabstop", buf->b_p_ts, NULL);
+    dict_add_nr_str(opts, "textmode", buf->b_p_tx, NULL);
+    dict_add_nr_str(opts, "textwidth", buf->b_p_tw, NULL);
+    dict_add_nr_str(opts, "wrapmargin", buf->b_p_wm, NULL);
+#ifdef FEAT_KEYMAP
+    dict_add_nr_str(opts, "keymap", 0L, buf->b_p_keymap);
+#endif
+#ifdef FEAT_QUICKFIX
+    dict_add_nr_str(opts, "grepprg", 0L, buf->b_p_gp);
+    dict_add_nr_str(opts, "makeprg", 0L, buf->b_p_mp);
+    dict_add_nr_str(opts, "errorformat", 0L, buf->b_p_efm);
+#endif
+    dict_add_nr_str(opts, "equalprg", 0L, buf->b_p_ep);
+    dict_add_nr_str(opts, "path", 0L, buf->b_p_path);
+    dict_add_nr_str(opts, "autoread", buf->b_p_ar, NULL);
+    dict_add_nr_str(opts, "tags", 0L, buf->b_p_tags);
+    dict_add_nr_str(opts, "tagcase", 0L, buf->b_p_tc);
+#ifdef FEAT_INS_EXPAND
+    dict_add_nr_str(opts, "dictionary", 0L, buf->b_p_dict);
+    dict_add_nr_str(opts, "thesaurus", 0L, buf->b_p_tsr);
+#endif
+    dict_add_nr_str(opts, "undolevels", buf->b_p_ul, NULL);
+#ifdef FEAT_PERSISTENT_UNDO
+    dict_add_nr_str(opts, "undofile", buf->b_p_udf, NULL);
+#endif
+#ifdef FEAT_LISP
+    dict_add_nr_str(opts, "lispwords", 0L, buf->b_p_lw);
+#endif
+#if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
+    dict_add_nr_str(opts, "balloonexpr", 0L, buf->b_p_bexpr);
+#endif
+#ifdef FEAT_CRYPT
+    dict_add_nr_str(opts, "cryptmethod", 0L, buf->b_p_cm);
+#endif
+
+    return opts;
+}
+
+/*
+ * Returns buffer options, variables and other attributes in a dictionary
+ */
+    static dict_T *
+get_buffer_info(buf_T *buf)
+{
+    dict_T     *dict;
+    dict_T     *opts;
+    dict_T     *vars;
+
+    dict = dict_alloc();
+    if (dict == NULL)
+       return NULL;
+
+    dict_add_nr_str(dict, "nr", buf->b_fnum, NULL);
+    dict_add_nr_str(dict, "name", 0L, buf->b_ffname);
+    dict_add_nr_str(dict, "lnum", buflist_findlnum(buf), NULL);
+    dict_add_nr_str(dict, "loaded", buf->b_ml.ml_mfp != NULL, NULL);
+    dict_add_nr_str(dict, "changed", bufIsChanged(buf), NULL);
+    dict_add_nr_str(dict, "changedtick", buf->b_changedtick, NULL);
+    dict_add_nr_str(dict, "hidden",
+                   buf->b_ml.ml_mfp != NULL && buf->b_nwindows == 0,
+                   NULL);
+
+    /* Copy buffer variables */
+    vars = dict_copy(buf->b_vars, TRUE, 0);
+    if (vars != NULL)
+       dict_add_dict(dict, "variables", vars);
+
+    /* Copy buffer options */
+    opts = get_buffer_options(buf);
+    if (opts != NULL)
+       dict_add_dict(dict, "options", opts);
+
+    return dict;
+}
+
+/*
+ * "getbufinfo()" function
+ */
+    static void
+f_getbufinfo(typval_T *argvars, typval_T *rettv)
+{
+    buf_T      *buf = NULL;
+    buf_T      *argbuf = NULL;
+    dict_T     *d;
+
+    if (argvars[0].v_type == VAR_UNKNOWN)
+    {
+       /* List of all the buffers */
+       if (rettv_list_alloc(rettv) != OK)
+           return;
+    }
+    else
+    {
+       /* Information about one buffer.  Argument specifies the buffer */
+       (void)get_tv_number(&argvars[0]);   /* issue errmsg if type error */
+       ++emsg_off;
+       argbuf = get_buf_tv(&argvars[0], FALSE);
+       --emsg_off;
+       if (argbuf == NULL)
+       {
+           (void)rettv_dict_alloc(rettv);
+           return;
+       }
+    }
+
+    /* Return information about all the buffers or a specified buffer */
+    for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+    {
+       if (argbuf != NULL && argbuf != buf)
+           continue;
+
+       d = get_buffer_info(buf);
+       if (argbuf != NULL)
+       {
+           rettv_dict_set(rettv, d);
+           return;
+       }
+
+       if (d != NULL)
+           list_append_dict(rettv->vval.v_list, d);
+    }
+}
+
 static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int 
retlist, typval_T *rettv);
 
 /*
@@ -13180,6 +13454,90 @@ f_getregtype(typval_T *argvars, typval_T *rettv)
     rettv->vval.v_string = vim_strsave(buf);
 }
 
+#ifdef FEAT_WINDOWS
+/*
+ * get_tabpage_info
+ * Returns information (variables, options, etc.) about a tab page
+ * as a dictionary
+ */
+    static dict_T *
+get_tabpage_info(tabpage_T *tp, int tp_idx)
+{
+    win_T      *wp;
+    dict_T     *dict;
+    dict_T     *vars;
+    int                nr;
+
+    dict = dict_alloc();
+    if (dict == NULL)
+       return NULL;
+
+    dict_add_nr_str(dict, "nr", tp_idx, NULL);
+
+    /* Count the number of windows in this tab page */
+    nr = 1;
+    for (wp = (tp == curtab) ? firstwin : tp->tp_firstwin;
+        wp != ((tp == curtab) ? lastwin : tp->tp_lastwin);
+        wp = wp->w_next)
+       nr++;
+    dict_add_nr_str(dict, "numwindows", nr, NULL);
+
+    /* Copy tabpage variables */
+    vars = dict_copy(tp->tp_vars, TRUE, 0);
+    if (vars != NULL)
+       dict_add_dict(dict, "variables", vars);
+
+    return dict;
+}
+#endif
+
+/*
+ * "gettabinfo()" function
+ */
+    static void
+f_gettabinfo(typval_T *argvars, typval_T *rettv)
+{
+#ifdef FEAT_WINDOWS
+    tabpage_T  *tp, *tparg = NULL;
+    dict_T     *d;
+    int                tpnr = 1;
+
+    if (argvars[0].v_type == VAR_UNKNOWN)
+    {
+       /* List of all the tab pages */
+       if (rettv_list_alloc(rettv) != OK)
+           return;
+    }
+    else
+    {
+       /* Information about one tab page */
+       tparg = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL));
+       if (tparg == NULL)
+       {
+           (void)rettv_dict_alloc(rettv);
+           return;
+       }
+    }
+
+    /* Get information about a specific tab page or all tab pages */
+    for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, tpnr++)
+    {
+       if (tparg != NULL && tp != tparg)
+           continue;
+
+       d = get_tabpage_info(tp, tpnr);
+       if (tparg != NULL)
+       {
+           rettv_dict_set(rettv, d);
+           return;
+       }
+
+       if (d != NULL)
+           list_append_dict(rettv->vval.v_list, d);
+    }
+#endif
+}
+
 /*
  * "gettabvar()" function
  */
@@ -13233,6 +13591,203 @@ f_gettabwinvar(typval_T *argvars, typval_T *rettv)
 }
 
 /*
+ * get_win_options
+ * Return all the window-local options in a dictionary.
+ */
+    static dict_T *
+get_win_options(win_T *wp)
+{
+    dict_T     *opts;
+
+    /* Copy window options */
+    opts = dict_alloc();
+    if (opts == NULL)
+       return NULL;
+
+#ifdef FEAT_ARABIC
+    dict_add_nr_str(opts, "arabic", wp->w_p_arab, NULL);
+#endif
+#ifdef FEAT_LINEBREAK
+    dict_add_nr_str(opts, "breakindent", wp->w_p_bri, NULL);
+    dict_add_nr_str(opts, "breakindentopt", 0L, wp->w_p_briopt);
+#endif
+#ifdef FEAT_DIFF
+    dict_add_nr_str(opts, "diff", wp->w_p_diff, NULL);
+#endif
+#ifdef FEAT_FOLDING
+    dict_add_nr_str(opts, "foldcolumn", wp->w_p_fdc, NULL);
+    dict_add_nr_str(opts, "foldenable", wp->w_p_fen, NULL);
+    dict_add_nr_str(opts, "foldignore", 0L, wp->w_p_fdi);
+    dict_add_nr_str(opts, "foldlevel", wp->w_p_fdl, NULL);
+    dict_add_nr_str(opts, "foldmethod", 0L, wp->w_p_fdm);
+    dict_add_nr_str(opts, "foldminlines", wp->w_p_fml, NULL);
+    dict_add_nr_str(opts, "foldnestmax", wp->w_p_fdn, NULL);
+# ifdef FEAT_EVAL
+    dict_add_nr_str(opts, "foldexpr", 0L, wp->w_p_fde);
+    dict_add_nr_str(opts, "foldtext", 0L, wp->w_p_fdt);
+# endif
+    dict_add_nr_str(opts, "foldmarker", 0L, wp->w_p_fmr);
+#endif
+#ifdef FEAT_LINEBREAK
+    dict_add_nr_str(opts, "linebreak", wp->w_p_lbr, NULL);
+#endif
+    dict_add_nr_str(opts, "list", wp->w_p_list, NULL);
+    dict_add_nr_str(opts, "number", wp->w_p_nu, NULL);
+    dict_add_nr_str(opts, "relativenumber", wp->w_p_rnu, NULL);
+#ifdef FEAT_LINEBREAK
+    dict_add_nr_str(opts, "numberwidth", wp->w_p_nuw, NULL);
+#endif
+#ifdef FEAT_WINDOWS
+    dict_add_nr_str(opts, "winfixheight", wp->w_p_wfh, NULL);
+    dict_add_nr_str(opts, "winfixwidth", wp->w_p_wfw, NULL);
+#endif
+#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
+    dict_add_nr_str(opts, "previewwindow", wp->w_p_pvw, NULL);
+#endif
+#ifdef FEAT_RIGHTLEFT
+    dict_add_nr_str(opts, "rightleft", wp->w_p_rl, NULL);
+    dict_add_nr_str(opts, "rightleftcmd", 0L, wp->w_p_rlc);
+#endif
+    dict_add_nr_str(opts, "scroll", wp->w_p_scr, NULL);
+#ifdef FEAT_SPELL
+    dict_add_nr_str(opts, "spell", wp->w_p_spell, NULL);
+#endif
+#ifdef FEAT_SYN_HL
+    dict_add_nr_str(opts, "cursorcolumn", wp->w_p_cuc, NULL);
+    dict_add_nr_str(opts, "cursorline", wp->w_p_cul, NULL);
+    dict_add_nr_str(opts, "colorcolumn", 0L, wp->w_p_cc);
+#endif
+#ifdef FEAT_STL_OPT
+    dict_add_nr_str(opts, "statusline", 0L, wp->w_p_stl);
+#endif
+#ifdef FEAT_SCROLLBIND
+    dict_add_nr_str(opts, "scrollbind", wp->w_p_scb, NULL);
+#endif
+    dict_add_nr_str(opts, "wrap", wp->w_p_wrap, NULL);
+#ifdef FEAT_CONCEAL
+    dict_add_nr_str(opts, "concealcursor", 0L, wp->w_p_cocu);
+    dict_add_nr_str(opts, "conceallevel", wp->w_p_cole, NULL);
+#endif
+#ifdef FEAT_CURSORBIND
+    dict_add_nr_str(opts, "cursorbind", wp->w_p_crb, NULL);
+#endif
+
+    return opts;
+}
+
+#ifdef FEAT_WINDOWS
+/*
+ * Returns information about a window as a dictionary
+ */
+    static dict_T *
+get_win_info(win_T *wp, short tpnr, short winnr)
+{
+    dict_T     *dict;
+    dict_T     *vars;
+    dict_T     *opts;
+
+    dict = dict_alloc();
+    if (dict == NULL)
+       return NULL;
+
+    dict_add_nr_str(dict, "tpnr", tpnr, NULL);
+    dict_add_nr_str(dict, "nr", winnr, NULL);
+    dict_add_nr_str(dict, "height", wp->w_height, NULL);
+    dict_add_nr_str(dict, "width", wp->w_width, NULL);
+    dict_add_nr_str(dict, "bufnum", wp->w_buffer->b_fnum, NULL);
+
+    /* Copy window variables */
+    vars = dict_copy(wp->w_vars, TRUE, 0);
+    if (vars != NULL)
+       dict_add_dict(dict, "variables", vars);
+
+    /* Copy window options */
+    opts = get_win_options(wp);
+    if (opts != NULL)
+       dict_add_dict(dict, "options", opts);
+
+    return dict;
+}
+#endif
+
+/*
+ * "getwininfo()" function
+ */
+    static void
+f_getwininfo(typval_T *argvars, typval_T *rettv)
+{
+#ifdef FEAT_WINDOWS
+    tabpage_T  *tp, *tparg = NULL;
+    win_T      *wp = NULL, *wparg = NULL;
+    dict_T     *d;
+    short      tpnr, winnr;
+#endif
+
+    if (argvars[0].v_type == VAR_UNKNOWN || argvars[1].v_type == VAR_UNKNOWN)
+    {
+       /* collect information about a list of windows */
+       if (rettv_list_alloc(rettv) != OK)
+           return;
+    }
+
+#ifdef FEAT_WINDOWS
+    if (argvars[0].v_type != VAR_UNKNOWN)
+    {
+       /* first argument is the tab page number */
+       tparg = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL));
+       if (tparg == NULL)
+       {
+           if (argvars[1].v_type != VAR_UNKNOWN)
+               /* return an empty dictionary */
+               (void)rettv_dict_alloc(rettv);
+           return;
+       }
+
+       if (argvars[1].v_type != VAR_UNKNOWN)
+       {
+           /* second argument is the window number */
+           wparg = find_win_by_nr(&argvars[1], tparg);
+           if (wparg == NULL)
+           {
+               (void)rettv_dict_alloc(rettv);
+               return;
+           }
+       }
+    }
+
+    /* collect information about either all the windows across all the tab
+     * pages or one particular window.
+     */
+    tpnr = 1;
+    for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, tpnr++)
+    {
+       if (tparg != NULL && tp != tparg)
+           continue;
+
+       wp = (tp == curtab) ? firstwin : tp->tp_firstwin;
+       winnr = 1;
+
+       for (; wp; wp = wp->w_next, winnr++)
+       {
+           if (wparg != NULL && wp != wparg)
+               continue;
+
+           d = get_win_info(wp, tpnr, winnr);
+           if (wparg != NULL)
+           {
+               /* found information about a specific window */
+               rettv_dict_set(rettv, d);
+               return;
+           }
+
+           if (d != NULL)
+               list_append_dict(rettv->vval.v_list, d);
+       }
+    }
+#endif
+}
+
+/*
  * "getwinposx()" function
  */
     static void
@@ -18563,6 +19118,7 @@ f_settabvar(typval_T *argvars, typval_T *rettv)
 
     rettv->vval.v_number = 0;
 
+#ifdef FEAT_WINDOWS
     if (check_restricted() || check_secure())
        return;
 
@@ -18598,6 +19154,7 @@ f_settabvar(typval_T *argvars, typval_T *rettv)
            goto_tabpage_tp(save_curtab, FALSE, FALSE);
 #endif
     }
+#endif
 }
 
 /*
@@ -20236,7 +20793,6 @@ f_tabpagebuflist(typval_T *argvars UNUSED, typval_T 
*rettv UNUSED)
 #endif
 }
 
-
 /*
  * "tabpagenr()" function
  */
diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak
index 2540abf..69eadee 100644
--- a/src/testdir/Make_all.mak
+++ b/src/testdir/Make_all.mak
@@ -168,6 +168,7 @@ SCRIPTS_GUI = test16.out
 NEW_TESTS = test_arglist.res \
            test_assert.res \
            test_backspace_opt.res \
+           test_bufwintabinfo.res \
            test_cdo.res \
            test_channel.res \
            test_hardcopy.res \
diff --git a/src/testdir/test_bufwintabinfo.vim 
b/src/testdir/test_bufwintabinfo.vim
new file mode 100644
index 0000000..9fa4c28
--- /dev/null
+++ b/src/testdir/test_bufwintabinfo.vim
@@ -0,0 +1,32 @@
+" Tests for the getbufinfo(), getwininfo() and gettabinfo() functions
+
+function Test_getbufwintabinfo()
+    1,$bwipeout
+    edit Xtestfile1
+    edit Xtestfile2
+    let buflist = getbufinfo()
+    call assert_equal(2, len(buflist))
+    call assert_match('Xtestfile1', buflist[0].name)
+    call assert_match('Xtestfile2', getbufinfo('Xtestfile2').name)
+    call assert_equal({}, getbufinfo(2016))
+
+    only | new
+    tabnew | new | new
+    tabfirst
+    let winlist = getwininfo()
+    call assert_equal(5, len(winlist))
+    call assert_equal(2, winlist[3].tpnr)
+    let winlist = getwininfo(2)
+    call assert_equal(3, len(winlist))
+    call assert_equal(1, getwininfo(1, 2).tpnr)
+    call assert_equal([], getwininfo(3))
+    call assert_equal({}, getwininfo(1,4))
+
+    let tablist = gettabinfo()
+    call assert_equal(2, len(tablist))
+    call assert_equal(3, tablist[1].numwindows)
+    call assert_equal(3, gettabinfo(2).numwindows)
+    call assert_equal({}, gettabinfo(3))
+
+    tabonly | only
+endfunction

Raspunde prin e-mail lui