]> granicus.if.org Git - vim/commitdiff
patch 7.4.1557 v7.4.1557
authorBram Moolenaar <Bram@vim.org>
Sun, 13 Mar 2016 17:07:30 +0000 (18:07 +0100)
committerBram Moolenaar <Bram@vim.org>
Sun, 13 Mar 2016 17:07:30 +0000 (18:07 +0100)
Problem:    Windows cannot be identified.
Solution:   Add a unique window number to each window and functions to use it.

runtime/doc/eval.txt
src/eval.c
src/proto/eval.pro
src/proto/window.pro
src/structs.h
src/testdir/Make_all.mak
src/testdir/test_window_id.vim [new file with mode: 0644]
src/version.c
src/window.c

index 370d64b443ffbf4162d0f38896220f0884372ba8..6e18df45f8660c5580686733614078e2b7c57d7c 100644 (file)
@@ -1,4 +1,4 @@
-*eval.txt*     For Vim version 7.4.  Last change: 2016 Mar 12
+*eval.txt*     For Vim version 7.4.  Last change: 2016 Mar 13
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -764,13 +764,23 @@ expressions are referring to the same |List| or |Dictionary| instance.  A copy
 of a |List| is different from the original |List|.  When using "is" without
 a |List| or a |Dictionary| it is equivalent to using "equal", using "isnot"
 equivalent to using "not equal".  Except that a different type means the
-values are different: "4 == '4'" is true, "4 is '4'" is false and "0 is []" is
-false and not an error. "is#"/"isnot#" and "is?"/"isnot?" can be used to match
-and ignore case.
+values are different: >
+       echo 4 == '4'
+       1
+       echo 4 is '4'
+       0
+       echo 0 is []
+       0
+"is#"/"isnot#" and "is?"/"isnot?" can be used to match and ignore case.
 
 When comparing a String with a Number, the String is converted to a Number,
-and the comparison is done on Numbers. This means that "0 == 'x'" is TRUE,
-because 'x' converted to a Number is zero.
+and the comparison is done on Numbers. This means that: >
+       echo 0 == 'x'
+       1
+because 'x' converted to a Number is zero.  However: >
+       echo [0] == ['x']
+       0
+Inside a List or Dictionary this conversion is not used.
 
 When comparing two Strings, this is done with strcmp() or stricmp().  This
 results in the mathematical difference (comparing byte values), not
@@ -2139,6 +2149,10 @@ values( {dict})                  List    values in {dict}
 virtcol( {expr})               Number  screen column of cursor or mark
 visualmode( [expr])            String  last visual mode used
 wildmenumode()                 Number  whether 'wildmenu' mode is active
+win_getid( [{win} [, {tab}]])  Number  get window ID for {win} in {tab}
+win_gotoid( {expr})            Number  go to window with ID {expr}
+win_id2tabwin( {expr})         List    get tab and window nr from window ID
+win_id2win( {expr})            Number  get window nr from window ID
 winbufnr( {nr})                        Number  buffer number of window {nr}
 wincol()                       Number  window column of the cursor
 winheight( {nr})               Number  height of window {nr}
@@ -7162,6 +7176,29 @@ wildmenumode()                                   *wildmenumode()*
                (Note, this needs the 'wildcharm' option set appropriately).
 
 
+win_getid([{win} [, {tab}]])                           *win_getid()*
+               Get the window ID for the specified window.
+               When {win} is missing use the current window.
+               With {win} this is the window number.  The top window has
+               number 1.
+               Without {tab} use the current tab, otherwise the tab with
+               number {tab}.  The first tab has number one.
+               Return zero if the window cannot be found.
+
+win_gotoid({expr})                                     *win_gotoid()*
+               Go to window with ID {expr}.  This may also change the current
+               tabpage.
+               Return 1 if successful, 0 if the window cannot be found.
+
+win_id2tabwin({expr}                                   *win_id2tabwin()*
+               Return a list with the tab number and window number of window
+               with ID {expr}: [tabnr, winnr].
+               Return [0, 0] if the window cannot be found.
+
+win_id2win({expr})                                     *win_id2win()*
+               Return the window number of window with ID {expr}.
+               Return 0 if the window cannot be found in the current tabpage.
+
                                                        *winbufnr()*
 winbufnr({nr}) The result is a Number, which is the number of the buffer
                associated with window {nr}.  When {nr} is zero, the number of
index 0b589fdc0f649196c3b77b2ec06d3e39531d76db..5025a52c1978786c14556fccbaad8538a1327380 100644 (file)
@@ -434,7 +434,6 @@ static int dict_equal(dict_T *d1, dict_T *d2, int ic, int recursive);
 static int tv_equal(typval_T *tv1, typval_T *tv2, int ic, int recursive);
 static long list_find_nr(list_T *l, long idx, int *errorp);
 static long list_idx_of_item(list_T *l, listitem_T *item);
-static int list_append_number(list_T *l, varnumber_T n);
 static int list_extend(list_T  *l1, list_T *l2, listitem_T *bef);
 static int list_concat(list_T *l1, list_T *l2, typval_T *tv);
 static list_T *list_copy(list_T *orig, int deep, int copyID);
@@ -808,6 +807,10 @@ static void f_values(typval_T *argvars, typval_T *rettv);
 static void f_virtcol(typval_T *argvars, typval_T *rettv);
 static void f_visualmode(typval_T *argvars, typval_T *rettv);
 static void f_wildmenumode(typval_T *argvars, typval_T *rettv);
+static void f_win_getid(typval_T *argvars, typval_T *rettv);
+static void f_win_gotoid(typval_T *argvars, typval_T *rettv);
+static void f_win_id2tabwin(typval_T *argvars, typval_T *rettv);
+static void f_win_id2win(typval_T *argvars, typval_T *rettv);
 static void f_winbufnr(typval_T *argvars, typval_T *rettv);
 static void f_wincol(typval_T *argvars, typval_T *rettv);
 static void f_winheight(typval_T *argvars, typval_T *rettv);
@@ -6469,7 +6472,7 @@ list_append_string(list_T *l, char_u *str, int len)
  * Append "n" to list "l".
  * Returns FAIL when out of memory.
  */
-    static int
+    int
 list_append_number(list_T *l, varnumber_T n)
 {
     listitem_T *li;
@@ -8385,6 +8388,10 @@ static struct fst
     {"virtcol",                1, 1, f_virtcol},
     {"visualmode",     0, 1, f_visualmode},
     {"wildmenumode",   0, 0, f_wildmenumode},
+    {"win_getid",      0, 2, f_win_getid},
+    {"win_gotoid",     1, 1, f_win_gotoid},
+    {"win_id2tabwin",  1, 1, f_win_id2tabwin},
+    {"win_id2win",     1, 1, f_win_id2win},
     {"winbufnr",       1, 1, f_winbufnr},
     {"wincol",         0, 0, f_wincol},
     {"winheight",      1, 1, f_winheight},
@@ -12661,6 +12668,43 @@ f_getwinposx(typval_T *argvars UNUSED, typval_T *rettv)
 #endif
 }
 
+/*
+ * "win_getid()" function
+ */
+    static void
+f_win_getid(typval_T *argvars, typval_T *rettv)
+{
+    rettv->vval.v_number = win_getid(argvars);
+}
+
+/*
+ * "win_gotoid()" function
+ */
+    static void
+f_win_gotoid(typval_T *argvars, typval_T *rettv)
+{
+    rettv->vval.v_number = win_gotoid(argvars);
+}
+
+/*
+ * "win_id2tabwin()" function
+ */
+    static void
+f_win_id2tabwin(typval_T *argvars, typval_T *rettv)
+{
+    if (rettv_list_alloc(rettv) != FAIL)
+       win_id2tabwin(argvars, rettv->vval.v_list);
+}
+
+/*
+ * "win_id2win()" function
+ */
+    static void
+f_win_id2win(typval_T *argvars, typval_T *rettv)
+{
+    rettv->vval.v_number = win_id2win(argvars);
+}
+
 /*
  * "getwinposy()" function
  */
index f5e0d19504bedb55448573f4960d7b1b18e6e910..7035f26e24b277ab4ebef85c931a63d15aae914a 100644 (file)
@@ -59,6 +59,7 @@ void list_append(list_T *l, listitem_T *item);
 int list_append_tv(list_T *l, typval_T *tv);
 int list_append_dict(list_T *list, dict_T *dict);
 int list_append_string(list_T *l, char_u *str, int len);
+int list_append_number(list_T *l, varnumber_T n);
 int list_insert_tv(list_T *l, typval_T *tv, listitem_T *item);
 void list_insert(list_T *l, listitem_T *ni, listitem_T *item);
 void vimlist_remove(list_T *l, listitem_T *item, listitem_T *item2);
index 613fe219bb093c89e885784901c92cdf3a05b66d..3c511e3c54e9956396a519c7ca639b135c32e50e 100644 (file)
@@ -83,4 +83,8 @@ void clear_matches(win_T *wp);
 matchitem_T *get_match(win_T *wp, int id);
 int get_win_number(win_T *wp, win_T *first_win);
 int get_tab_number(tabpage_T *tp);
+int win_getid(typval_T *argvars);
+int win_gotoid(typval_T *argvars);
+void win_id2tabwin(typval_T *argvars, list_T *list);
+int win_id2win(typval_T *argvars);
 /* vim: set ft=c : */
index 6bf21263ab58c7a5fed09a06450a4791f3bb7c5f..4aa7415f0fbe714caed668f2e0f1f72f9e3d674d 100644 (file)
@@ -2273,6 +2273,8 @@ struct matchitem
  */
 struct window_S
 {
+    int                w_id;               /* unique window ID */
+
     buf_T      *w_buffer;          /* buffer we are a window into (used
                                       often, keep it the first item!) */
 
index 5ad1718c6f49fbb0798b37b0eca3f4f2a8759e27..233ca12dfdb9299ca32576934c50a054b68dc39c 100644 (file)
@@ -186,6 +186,7 @@ NEW_TESTS = test_arglist.res \
            test_viminfo.res \
            test_viml.res \
            test_visual.res \
+           test_window_id.res \
            test_alot.res
 
 
diff --git a/src/testdir/test_window_id.vim b/src/testdir/test_window_id.vim
new file mode 100644 (file)
index 0000000..b9e9f45
--- /dev/null
@@ -0,0 +1,71 @@
+" Test using the window ID.
+
+func Test_win_getid()
+  edit one
+  let id1 = win_getid()
+  split two
+  let id2 = win_getid()
+  split three
+  let id3 = win_getid()
+  tabnew
+  edit four
+  let id4 = win_getid()
+  split five
+  let id5 = win_getid()
+  tabnext
+
+  wincmd w
+  call assert_equal("two", expand("%"))
+  call assert_equal(id2, win_getid())
+  let nr2 = winnr()
+  wincmd w
+  call assert_equal("one", expand("%"))
+  call assert_equal(id1, win_getid())
+  let nr1 = winnr()
+  wincmd w
+  call assert_equal("three", expand("%"))
+  call assert_equal(id3, win_getid())
+  let nr3 = winnr()
+  tabnext
+  call assert_equal("five", expand("%"))
+  call assert_equal(id5, win_getid())
+  let nr5 = winnr()
+  wincmd w
+  call assert_equal("four", expand("%"))
+  call assert_equal(id4, win_getid())
+  let nr4 = winnr()
+  tabnext
+
+  exe nr1 . "wincmd w"
+  call assert_equal(id1, win_getid())
+  exe nr2 . "wincmd w"
+  call assert_equal(id2, win_getid())
+  exe nr3 . "wincmd w"
+  call assert_equal(id3, win_getid())
+  tabnext
+  exe nr4 . "wincmd w"
+  call assert_equal(id4, win_getid())
+  exe nr5 . "wincmd w"
+  call assert_equal(id5, win_getid())
+
+  call win_gotoid(id2)
+  call assert_equal("two", expand("%"))
+  call win_gotoid(id4)
+  call assert_equal("four", expand("%"))
+  call win_gotoid(id1)
+  call assert_equal("one", expand("%"))
+  call win_gotoid(id5)
+  call assert_equal("five", expand("%"))
+
+  call assert_equal(0, win_id2win(9999))
+  call assert_equal(nr5, win_id2win(id5))
+  call assert_equal(0, win_id2win(id1))
+  tabnext
+  call assert_equal(nr1, win_id2win(id1))
+
+  call assert_equal([0, 0], win_id2tabwin(9999))
+  call assert_equal([1, nr2], win_id2tabwin(id2))
+  call assert_equal([2, nr4], win_id2tabwin(id4))
+
+  only!
+endfunc
index 9c15aafc810fb9ac2ff93136ba2e77fce0622758..bed7a460420c2b5e4ca55b33fee7ccc35cc736d3 100644 (file)
@@ -743,6 +743,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1557,
 /**/
     1556,
 /**/
index 7dfbe5a991e2e0c375b251d52d9e6c4701e86198..b6111bd15cda60a885fd220de8cf27de4da0b638 100644 (file)
@@ -4541,6 +4541,8 @@ buf_jump_open_tab(buf_T *buf)
 }
 #endif
 
+static int last_win_id = 0;
+
 /*
  * Allocate a window structure and link it in the window list when "hidden" is
  * FALSE.
@@ -4563,6 +4565,8 @@ win_alloc(win_T *after UNUSED, int hidden UNUSED)
        return NULL;
     }
 
+    new_wp->w_id = ++last_win_id;
+
 #ifdef FEAT_EVAL
     /* init w: variables */
     new_wp->w_vars = dict_alloc();
@@ -7198,3 +7202,99 @@ frame_check_width(frame_T *topfrp, int width)
 }
 #endif
 
+#if defined(FEAT_EVAL) || defined(PROTO)
+    int
+win_getid(typval_T *argvars)
+{
+    int            winnr;
+    win_T   *wp;
+
+    if (argvars[0].v_type == VAR_UNKNOWN)
+       return curwin->w_id;
+    winnr = get_tv_number(&argvars[0]);
+    if (winnr > 0)
+    {
+       if (argvars[1].v_type == VAR_UNKNOWN)
+           wp = firstwin;
+       else
+       {
+           tabpage_T   *tp;
+           int         tabnr = get_tv_number(&argvars[1]);
+
+           for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
+               if (--tabnr == 0)
+                   break;
+           if (tp == NULL)
+               return -1;
+           wp = tp->tp_firstwin;
+       }
+       for ( ; wp != NULL; wp = wp->w_next)
+           if (--winnr == 0)
+               return wp->w_id;
+    }
+    return 0;
+}
+
+    int
+win_gotoid(typval_T *argvars)
+{
+    win_T      *wp;
+    tabpage_T   *tp;
+    int                id = get_tv_number(&argvars[0]);
+
+    for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
+       for (wp = tp == curtab ? firstwin : tp->tp_firstwin;
+                                                 wp != NULL; wp = wp->w_next)
+           if (wp->w_id == id)
+           {
+               goto_tabpage_win(tp, wp);
+               return 1;
+           }
+    return 0;
+}
+
+    void
+win_id2tabwin(typval_T *argvars, list_T *list)
+{
+    win_T      *wp;
+    tabpage_T   *tp;
+    int                winnr = 1;
+    int                tabnr = 1;
+    int                id = get_tv_number(&argvars[0]);
+
+    for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
+    {
+       for (wp = tp == curtab ? firstwin : tp->tp_firstwin;
+                                                 wp != NULL; wp = wp->w_next)
+       {
+           if (wp->w_id == id)
+           {
+               list_append_number(list, tabnr);
+               list_append_number(list, winnr);
+               return;
+           }
+           ++winnr;
+       }
+       ++tabnr;
+       winnr = 1;
+    }
+    list_append_number(list, 0);
+    list_append_number(list, 0);
+}
+
+    int
+win_id2win(typval_T *argvars)
+{
+    win_T   *wp;
+    int            nr = 1;
+    int            id = get_tv_number(&argvars[0]);
+
+    for (wp = firstwin; wp != NULL; wp = wp->w_next)
+    {
+       if (wp->w_id == id)
+           return nr;
+       ++nr;
+    }
+    return 0;
+}
+#endif