vim-patch:7.4.1557 (#5117)

Problem:    Windows cannot be identified.
Solution:   Add a unique window number to each window and functions to use it.

86edef664e
This commit is contained in:
prollings
2016-08-04 14:22:45 +10:00
committed by Justin M. Keyes
parent 08d11bd42f
commit 0d93cd6c46
7 changed files with 242 additions and 9 deletions

View File

@@ -754,13 +754,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 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" 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 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 values are different: >
false and not an error. "is#"/"isnot#" and "is?"/"isnot?" can be used to match echo 4 == '4'
and ignore case. 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, 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, and the comparison is done on Numbers. This means that: >
because 'x' converted to a Number is zero. 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 When comparing two Strings, this is done with strcmp() or stricmp(). This
results in the mathematical difference (comparing byte values), not results in the mathematical difference (comparing byte values), not
@@ -2138,6 +2148,10 @@ values({dict}) List values in {dict}
virtcol({expr}) Number screen column of cursor or mark virtcol({expr}) Number screen column of cursor or mark
visualmode([expr]) String last visual mode used visualmode([expr]) String last visual mode used
wildmenumode() Number whether 'wildmenu' mode is active 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 window nr from window ID
win_id2win( {expr}) Number get window nr from window ID
winbufnr({nr}) Number buffer number of window {nr} winbufnr({nr}) Number buffer number of window {nr}
wincol() Number window column of the cursor wincol() Number window column of the cursor
winheight({nr}) Number height of window {nr} winheight({nr}) Number height of window {nr}
@@ -7192,6 +7206,29 @@ wildmenumode() *wildmenumode()*
(Note, this needs the 'wildcharm' option set appropriately). (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()*
winbufnr({nr}) The result is a Number, which is the number of the buffer 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 associated with window {nr}. When {nr} is zero, the number of

View File

@@ -937,8 +937,9 @@ struct matchitem {
*/ */
struct window_S { struct window_S {
uint64_t handle; uint64_t handle;
buf_T *w_buffer; /* buffer we are a window into (used int w_id; ///< unique window ID
often, keep it the first item!) */ buf_T *w_buffer; ///< buffer we are a window into (used
///< often, keep it the first item!)
synblock_T *w_s; /* for :ownsyntax */ synblock_T *w_s; /* for :ownsyntax */

View File

@@ -6987,6 +6987,10 @@ static struct fst {
{ "virtcol", 1, 1, f_virtcol }, { "virtcol", 1, 1, f_virtcol },
{ "visualmode", 0, 1, f_visualmode }, { "visualmode", 0, 1, f_visualmode },
{ "wildmenumode", 0, 0, f_wildmenumode }, { "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 }, { "winbufnr", 1, 1, f_winbufnr },
{ "wincol", 0, 0, f_wincol }, { "wincol", 0, 0, f_wincol },
{ "winheight", 1, 1, f_winheight }, { "winheight", 1, 1, f_winheight },
@@ -17150,6 +17154,32 @@ static void f_wildmenumode(typval_T *argvars, typval_T *rettv)
rettv->vval.v_number = 1; rettv->vval.v_number = 1;
} }
/// "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);
}
/* /*
* "winbufnr(nr)" function * "winbufnr(nr)" function
*/ */
@@ -18437,7 +18467,7 @@ static void init_tv(typval_T *varp)
* caller of incompatible types: it sets *denote to TRUE if "denote" * caller of incompatible types: it sets *denote to TRUE if "denote"
* is not NULL or returns -1 otherwise. * is not NULL or returns -1 otherwise.
*/ */
static long get_tv_number(typval_T *varp) long get_tv_number(typval_T *varp)
{ {
int error = FALSE; int error = FALSE;

View File

@@ -39,6 +39,7 @@ NEW_TESTS = \
test_timers.res \ test_timers.res \
test_viml.res \ test_viml.res \
test_visual.res \ test_visual.res \
test_window_id.res \
test_alot.res test_alot.res
SCRIPTS_GUI := test16.out SCRIPTS_GUI := test16.out

View File

@@ -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

View File

@@ -720,7 +720,7 @@ static int included_patches[] = {
// 1560 NA // 1560 NA
// 1559, // 1559,
// 1558, // 1558,
// 1557, 1557,
// 1556 NA // 1556 NA
// 1555 NA // 1555 NA
1554, 1554,

View File

@@ -3683,6 +3683,8 @@ win_T *buf_jump_open_tab(buf_T *buf)
return NULL; return NULL;
} }
static int last_win_id = 0;
/* /*
* Allocate a window structure and link it in the window list when "hidden" is * Allocate a window structure and link it in the window list when "hidden" is
* FALSE. * FALSE.
@@ -3695,6 +3697,7 @@ static win_T *win_alloc(win_T *after, int hidden)
win_T *new_wp = xcalloc(1, sizeof(win_T)); win_T *new_wp = xcalloc(1, sizeof(win_T));
handle_register_window(new_wp); handle_register_window(new_wp);
win_alloc_lines(new_wp); win_alloc_lines(new_wp);
new_wp->w_id = ++last_win_id;
/* init w: variables */ /* init w: variables */
new_wp->w_vars = dict_alloc(); new_wp->w_vars = dict_alloc();
@@ -5674,3 +5677,93 @@ static bool frame_check_width(frame_T *topfrp, int width)
} }
return true; return true;
} }
int win_getid(typval_T *argvars)
{
if (argvars[0].v_type == VAR_UNKNOWN) {
return curwin->w_id;
}
int winnr = get_tv_number(&argvars[0]);
win_T *wp;
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;
}