diff src/evalfunc.c @ 9858:3e96d9ed2ca1 v7.4.2204

commit https://github.com/vim/vim/commit/b5ae48e9ffd3b8eb6ca4057de11f1bddcde8ce6f Author: Bram Moolenaar <Bram@vim.org> Date: Fri Aug 12 22:23:25 2016 +0200 patch 7.4.2204 Problem: It is not easy to get information about buffers, windows and tabpages. Solution: Add getbufinfo(), getwininfo() and gettabinfo(). (Yegappan Lakshmanan)
author Christian Brabandt <cb@256bit.org>
date Fri, 12 Aug 2016 22:30:07 +0200
parents 67781bb0a61a
children 74f67cb4f7e1
line wrap: on
line diff
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -152,6 +152,7 @@ static void f_funcref(typval_T *argvars,
 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);
@@ -179,8 +180,10 @@ static void f_getpos(typval_T *argvars, 
 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);
@@ -572,6 +575,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},
@@ -599,8 +603,10 @@ static struct fst
     {"getqflist",	0, 1, 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, 1, f_getwininfo},
     {"getwinposx",	0, 0, f_getwinposx},
     {"getwinposy",	0, 0, f_getwinposy},
     {"getwinvar",	2, 3, f_getwinvar},
@@ -3882,6 +3888,161 @@ f_get(typval_T *argvars, typval_T *rettv
 	copy_tv(tv, rettv);
 }
 
+#ifdef FEAT_SIGNS
+/*
+ * Returns information about signs placed in a buffer as list of dicts.
+ */
+    static void
+get_buffer_signs(buf_T *buf, list_T *l)
+{
+    signlist_T	*sign;
+
+    for (sign = buf->b_signlist; sign; sign = sign->next)
+    {
+	dict_T *d = dict_alloc();
+
+	if (d != NULL)
+	{
+	    dict_add_nr_str(d, "id", sign->id, NULL);
+	    dict_add_nr_str(d, "lnum", sign->lnum, NULL);
+	    dict_add_nr_str(d, "name", 0L,
+		    vim_strsave(sign_typenr2name(sign->typenr)));
+
+	    list_append_dict(l, d);
+	}
+    }
+}
+#endif
+
+/*
+ * 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;
+    tabpage_T	*tp;
+    win_T	*wp;
+    list_T	*windows;
+
+    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 != NULL ? buf->b_ffname : (char_u *)"");
+    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, "listed", buf->b_p_bl, 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_winbuf_options(TRUE);
+    if (opts != NULL)
+	dict_add_dict(dict, "options", opts);
+
+    /* List of windows displaying this buffer */
+    windows = list_alloc();
+    if (windows != NULL)
+    {
+	FOR_ALL_TAB_WINDOWS(tp, wp)
+	    if (wp->w_buffer == buf)
+		list_append_number(windows, (varnumber_T)wp->w_id);
+	dict_add_list(dict, "windows", windows);
+    }
+
+#ifdef FEAT_SIGNS
+    if (buf->b_signlist != NULL)
+    {
+	/* List of signs placed in this buffer */
+	list_T	*signs = list_alloc();
+	if (signs != NULL)
+	{
+	    get_buffer_signs(buf, signs);
+	    dict_add_list(dict, "signs", signs);
+	}
+    }
+#endif
+
+    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;
+    int		filtered = FALSE;
+    int		sel_buflisted = FALSE;
+    int		sel_bufloaded = FALSE;
+
+    if (rettv_list_alloc(rettv) != OK)
+	return;
+
+    /* List of all the buffers or selected buffers */
+    if (argvars[0].v_type == VAR_DICT)
+    {
+	dict_T	*sel_d = argvars[0].vval.v_dict;
+
+	if (sel_d != NULL)
+	{
+	    dictitem_T	*di;
+
+	    filtered = TRUE;
+
+	    di = dict_find(sel_d, (char_u *)"buflisted", -1);
+	    if (di != NULL && get_tv_number(&di->di_tv))
+		sel_buflisted = TRUE;
+
+	    di = dict_find(sel_d, (char_u *)"bufloaded", -1);
+	    if (di != NULL && get_tv_number(&di->di_tv))
+		sel_bufloaded = TRUE;
+	}
+    }
+    else if (argvars[0].v_type != VAR_UNKNOWN)
+    {
+	/* 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)
+	    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;
+	if (filtered && ((sel_bufloaded && buf->b_ml.ml_mfp == NULL)
+					   || (sel_buflisted && !buf->b_p_bl)))
+	    continue;
+
+	d = get_buffer_info(buf);
+	if (d != NULL)
+	    list_append_dict(rettv->vval.v_list, d);
+	if (argbuf != NULL)
+	    return;
+    }
+}
+
 static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retlist, typval_T *rettv);
 
 /*
@@ -4817,6 +4978,79 @@ f_getregtype(typval_T *argvars, typval_T
     rettv->vval.v_string = vim_strsave(buf);
 }
 
+#ifdef FEAT_WINDOWS
+/*
+ * 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;
+    list_T	*l;
+
+    dict = dict_alloc();
+    if (dict == NULL)
+	return NULL;
+
+    dict_add_nr_str(dict, "nr", tp_idx, NULL);
+
+    l = list_alloc();
+    if (l != NULL)
+    {
+	for (wp = (tp == curtab) ? firstwin : tp->tp_firstwin;
+		wp; wp = wp->w_next)
+	    list_append_number(l, (varnumber_T)wp->w_id);
+	dict_add_list(dict, "windows", l);
+    }
+
+    /* 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 (rettv_list_alloc(rettv) != OK)
+	return;
+
+    if (argvars[0].v_type != VAR_UNKNOWN)
+    {
+	/* Information about one tab page */
+	tparg = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL));
+	if (tparg == NULL)
+	    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 (d != NULL)
+	    list_append_dict(rettv->vval.v_list, d);
+	if (tparg != NULL)
+	    return;
+    }
+#endif
+}
+
 /*
  * "gettabvar()" function
  */
@@ -4869,6 +5103,89 @@ f_gettabwinvar(typval_T *argvars, typval
     getwinvar(argvars, rettv, 1);
 }
 
+#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, "winid", wp->w_id, 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_winbuf_options(FALSE);
+    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;
+    win_T	*wp = NULL, *wparg = NULL;
+    dict_T	*d;
+    short	tabnr, winnr;
+#endif
+
+    if (rettv_list_alloc(rettv) != OK)
+	return;
+
+#ifdef FEAT_WINDOWS
+    if (argvars[0].v_type != VAR_UNKNOWN)
+    {
+	wparg = win_id2wp(argvars);
+	if (wparg == NULL)
+	    return;
+    }
+
+    /* Collect information about either all the windows across all the tab
+     * pages or one particular window.
+     */
+    tabnr = 1;
+    for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, tabnr++)
+    {
+	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, tabnr, winnr);
+	    if (d != NULL)
+		list_append_dict(rettv->vval.v_list, d);
+	    if (wparg != NULL)
+		/* found information about a specific window */
+		return;
+	}
+    }
+#endif
+}
+
 /*
  * "getwinposx()" function
  */