Merge pull request #5613 from jamessan/vim-7.4.2183

vim-patch:7.4.2183,7.4.2194,7.4.2201,7.4.2204,0952131,7.4.2215,7.4.2225,7.4.2226,7.4.2272,7.4.2273,7.4.2277,7.4.2294
This commit is contained in:
James McCoy
2017-01-01 15:12:33 -05:00
committed by GitHub
27 changed files with 1336 additions and 447 deletions

View File

@@ -237,6 +237,8 @@ typedef struct {
# define w_p_crb w_onebuf_opt.wo_crb /* 'cursorbind' */
int wo_crb_save; /* 'cursorbind' state saved for diff mode*/
# define w_p_crb_save w_onebuf_opt.wo_crb_save
char_u *wo_scl;
# define w_p_scl w_onebuf_opt.wo_scl // 'signcolumn'
int wo_scriptID[WV_COUNT]; /* SIDs for window-local options */
# define w_p_scriptID w_onebuf_opt.wo_scriptID

View File

@@ -5708,7 +5708,7 @@ comp_textwidth (
textwidth -= 1;
textwidth -= curwin->w_p_fdc;
if (curwin->w_buffer->b_signlist != NULL) {
if (signcolumn_on(curwin)) {
textwidth -= 1;
}

View File

@@ -6611,6 +6611,23 @@ int dict_add_list(dict_T *d, char *key, list_T *list)
return OK;
}
/// Add a dict entry to dictionary "d".
/// Returns FAIL when out of memory and when key already exists.
int dict_add_dict(dict_T *d, char *key, dict_T *dict)
{
dictitem_T *item = dictitem_alloc((char_u *)key);
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;
}
/// Set all existing keys in "dict" as read-only.
///
/// This does not protect against adding new keys to the Dictionary.
@@ -9832,6 +9849,118 @@ static void f_get(typval_T *argvars, typval_T *rettv, FunPtr fptr)
copy_tv(tv, rettv);
}
/// Returns information about signs placed in a buffer as list of dicts.
static void get_buffer_signs(buf_T *buf, list_T *l)
{
for (signlist_T *sign = buf->b_signlist; sign; sign = sign->next) {
dict_T *d = dict_alloc();
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, sign_typenr2name(sign->typenr));
list_append_dict(l, d);
}
}
/// Returns buffer options, variables and other attributes in a dictionary.
static dict_T *get_buffer_info(buf_T *buf)
{
dict_T *dict = dict_alloc();
dict_add_nr_str(dict, "bufnr", 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);
// Get a reference to buffer variables
dict_add_dict(dict, "variables", buf->b_vars);
// List of windows displaying this buffer
list_T *windows = list_alloc();
FOR_ALL_TAB_WINDOWS(tp, wp) {
if (wp->w_buffer == buf) {
list_append_number(windows, (varnumber_T)wp->handle);
}
}
dict_add_list(dict, "windows", windows);
if (buf->b_signlist != NULL) {
// List of signs placed in this buffer
list_T *signs = list_alloc();
get_buffer_signs(buf, signs);
dict_add_list(dict, "signs", signs);
}
return dict;
}
/// "getbufinfo()" function
static void f_getbufinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
buf_T *argbuf = NULL;
bool filtered = false;
bool sel_buflisted = false;
bool sel_bufloaded = false;
rettv_list_alloc(rettv);
// 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_ALL_BUFFERS(buf) {
if (argbuf != NULL && argbuf != buf) {
continue;
}
if (filtered && ((sel_bufloaded && buf->b_ml.ml_mfp == NULL)
|| (sel_buflisted && !buf->b_p_bl))) {
continue;
}
dict_T *d = get_buffer_info(buf);
if (d != NULL) {
list_append_dict(rettv->vval.v_list, d);
}
if (argbuf != NULL) {
return;
}
}
}
/*
* Get line or list of lines from buffer "buf" into "rettv".
@@ -9920,9 +10049,21 @@ static void f_getbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
save_curbuf = curbuf;
curbuf = buf;
if (*varname == '&') { /* buffer-local-option */
if (get_option_tv(&varname, rettv, TRUE) == OK)
done = TRUE;
if (*varname == '&') { // buffer-local-option
if (varname[1] == NUL) {
// get all buffer-local options in a dict
dict_T *opts = get_winbuf_options(true);
if (opts != NULL) {
rettv->v_type = VAR_DICT;
rettv->vval.v_dict = opts;
opts->dv_refcount++;
done = true;
}
} else if (get_option_tv(&varname, rettv, true) == OK) {
// buffer-local-option
done = true;
}
} else if (STRCMP(varname, "changedtick") == 0) {
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = curbuf->b_changedtick;
@@ -10654,6 +10795,58 @@ static void f_getregtype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_string = (char_u *)xstrdup(buf);
}
/// Returns information (variables, options, etc.) about a tab page
/// as a dictionary.
static dict_T *get_tabpage_info(tabpage_T *tp, int tp_idx)
{
dict_T *dict = dict_alloc();
dict_add_nr_str(dict, "tabnr", tp_idx, NULL);
list_T *l = list_alloc();
FOR_ALL_WINDOWS_IN_TAB(wp, tp) {
list_append_number(l, (varnumber_T)wp->handle);
}
dict_add_list(dict, "windows", l);
// Make a reference to tabpage variables
dict_add_dict(dict, "variables", tp->tp_vars);
return dict;
}
/// "gettabinfo()" function
static void f_gettabinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
tabpage_T *tparg = NULL;
rettv_list_alloc(rettv);
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
int tpnr = 0;
FOR_ALL_TABS(tp) {
tpnr++;
if (tparg != NULL && tp != tparg) {
continue;
}
dict_T *d = get_tabpage_info(tp, tpnr);
if (d != NULL) {
list_append_dict(rettv->vval.v_list, d);
}
if (tparg != NULL) {
return;
}
}
}
/*
* "gettabvar()" function
*/
@@ -10701,6 +10894,66 @@ static void f_gettabwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
getwinvar(argvars, rettv, 1);
}
/// Returns information about a window as a dictionary.
static dict_T *get_win_info(win_T *wp, int16_t tpnr, int16_t winnr)
{
dict_T *dict = dict_alloc();
dict_add_nr_str(dict, "tabnr", tpnr, NULL);
dict_add_nr_str(dict, "winnr", winnr, NULL);
dict_add_nr_str(dict, "winid", wp->handle, 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, "bufnr", wp->w_buffer->b_fnum, NULL);
dict_add_nr_str(dict, "quickfix", bt_quickfix(wp->w_buffer), NULL);
dict_add_nr_str(dict, "loclist",
(bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL),
NULL);
// Add a reference to window variables
dict_add_dict(dict, "variables", wp->w_vars);
return dict;
}
/// "getwininfo()" function
static void f_getwininfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
win_T *wparg = NULL;
rettv_list_alloc(rettv);
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.
int16_t tabnr = 0;
FOR_ALL_TABS(tp) {
tabnr++;
int16_t winnr = 0;
FOR_ALL_WINDOWS_IN_TAB(wp, tp) {
if (wparg != NULL && wp != wparg) {
continue;
}
winnr++;
dict_T *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;
}
}
}
}
/*
* "getwinposx()" function
*/
@@ -10820,8 +11073,19 @@ getwinvar (
bool need_switch_win = tp != curtab || win != curwin;
if (!need_switch_win
|| switch_win(&oldcurwin, &oldtabpage, win, tp, true) == OK) {
if (*varname == '&') { // window-local-option
if (get_option_tv(&varname, rettv, 1) == OK) {
if (*varname == '&') {
if (varname[1] == NUL) {
// get all window-local options in a dict
dict_T *opts = get_winbuf_options(false);
if (opts != NULL) {
rettv->v_type = VAR_DICT;
rettv->vval.v_dict = opts;
opts->dv_refcount++;
done = true;
}
} else if (get_option_tv(&varname, rettv, 1) == OK) {
// window-local-option
done = true;
}
} else {

View File

@@ -106,6 +106,7 @@ return {
['function']={args={1, 3}},
garbagecollect={args={0, 1}},
get={args={2, 3}},
getbufinfo={args={0, 1}},
getbufline={args={2, 3}},
getbufvar={args={2, 3}},
getchar={args={0, 1}},
@@ -131,8 +132,10 @@ return {
getqflist={},
getreg={args={0, 3}},
getregtype={args={0, 1}},
gettabinfo={args={0, 1}},
gettabvar={args={2, 3}},
gettabwinvar={args={3, 4}},
getwininfo={args={0, 1}},
getwinposx={},
getwinposy={},
getwinvar={args={2, 3}},

View File

@@ -5351,385 +5351,330 @@ static int sign_cmd_idx(
*/
void ex_sign(exarg_T *eap)
{
char_u *arg = eap->arg;
char_u *p;
int idx;
sign_T *sp;
sign_T *sp_prev;
char_u *arg = eap->arg;
char_u *p;
int idx;
sign_T *sp;
sign_T *sp_prev;
/* Parse the subcommand. */
p = skiptowhite(arg);
idx = sign_cmd_idx(arg, p);
if (idx == SIGNCMD_LAST)
{
EMSG2(_("E160: Unknown sign command: %s"), arg);
return;
// Parse the subcommand.
p = skiptowhite(arg);
idx = sign_cmd_idx(arg, p);
if (idx == SIGNCMD_LAST) {
EMSG2(_("E160: Unknown sign command: %s"), arg);
return;
}
arg = skipwhite(p);
if (idx <= SIGNCMD_LIST) {
// Define, undefine or list signs.
if (idx == SIGNCMD_LIST && *arg == NUL) {
// ":sign list": list all defined signs
for (sp = first_sign; sp != NULL && !got_int; sp = sp->sn_next) {
sign_list_defined(sp);
}
} else if (*arg == NUL) {
EMSG(_("E156: Missing sign name"));
} else {
// Isolate the sign name. If it's a number skip leading zeroes,
// so that "099" and "99" are the same sign. But keep "0".
p = skiptowhite(arg);
if (*p != NUL) {
*p++ = NUL;
}
while (arg[0] == '0' && arg[1] != NUL) {
arg++;
}
sp_prev = NULL;
for (sp = first_sign; sp != NULL; sp = sp->sn_next) {
if (STRCMP(sp->sn_name, arg) == 0) {
break;
}
sp_prev = sp;
}
if (idx == SIGNCMD_DEFINE) {
// ":sign define {name} ...": define a sign
if (sp == NULL) {
sign_T *lp;
int start = next_sign_typenr;
// Allocate a new sign.
sp = xcalloc(1, sizeof(sign_T));
// Check that next_sign_typenr is not already being used.
// This only happens after wrapping around. Hopefully
// another one got deleted and we can use its number.
for (lp = first_sign; lp != NULL; ) {
if (lp->sn_typenr == next_sign_typenr) {
next_sign_typenr++;
if (next_sign_typenr == MAX_TYPENR) {
next_sign_typenr = 1;
}
if (next_sign_typenr == start) {
xfree(sp);
EMSG(_("E612: Too many signs defined"));
return;
}
lp = first_sign; // start all over
continue;
}
lp = lp->sn_next;
}
sp->sn_typenr = next_sign_typenr;
if (++next_sign_typenr == MAX_TYPENR) {
next_sign_typenr = 1; // wrap around
}
sp->sn_name = vim_strsave(arg);
// add the new sign to the list of signs
if (sp_prev == NULL) {
first_sign = sp;
} else {
sp_prev->sn_next = sp;
}
}
// set values for a defined sign.
for (;;) {
arg = skipwhite(p);
if (*arg == NUL) {
break;
}
p = skiptowhite_esc(arg);
if (STRNCMP(arg, "icon=", 5) == 0) {
arg += 5;
xfree(sp->sn_icon);
sp->sn_icon = vim_strnsave(arg, (int)(p - arg));
backslash_halve(sp->sn_icon);
} else if (STRNCMP(arg, "text=", 5) == 0) {
char_u *s;
int cells;
int len;
arg += 5;
// Count cells and check for non-printable chars
cells = 0;
for (s = arg; s < p; s += (*mb_ptr2len)(s)) {
if (!vim_isprintc((*mb_ptr2char)(s))) {
break;
}
cells += (*mb_ptr2cells)(s);
}
// Currently must be one or two display cells
if (s != p || cells < 1 || cells > 2) {
*p = NUL;
EMSG2(_("E239: Invalid sign text: %s"), arg);
return;
}
xfree(sp->sn_text);
// Allocate one byte more if we need to pad up
// with a space.
len = (int)(p - arg + ((cells == 1) ? 1 : 0));
sp->sn_text = vim_strnsave(arg, len);
if (cells == 1) {
STRCPY(sp->sn_text + len - 1, " ");
}
} else if (STRNCMP(arg, "linehl=", 7) == 0) {
arg += 7;
sp->sn_line_hl = syn_check_group(arg, (int)(p - arg));
} else if (STRNCMP(arg, "texthl=", 7) == 0) {
arg += 7;
sp->sn_text_hl = syn_check_group(arg, (int)(p - arg));
} else {
EMSG2(_(e_invarg2), arg);
return;
}
}
} else if (sp == NULL) {
EMSG2(_("E155: Unknown sign: %s"), arg);
} else if (idx == SIGNCMD_LIST) {
// ":sign list {name}"
sign_list_defined(sp);
} else {
// ":sign undefine {name}"
sign_undefine(sp, sp_prev);
}
}
arg = skipwhite(p);
} else {
int id = -1;
linenr_T lnum = -1;
char_u *sign_name = NULL;
char_u *arg1;
if (idx <= SIGNCMD_LIST)
{
/*
* Define, undefine or list signs.
*/
if (idx == SIGNCMD_LIST && *arg == NUL)
{
/* ":sign list": list all defined signs */
for (sp = first_sign; sp != NULL && !got_int; sp = sp->sn_next)
sign_list_defined(sp);
}
else if (*arg == NUL)
EMSG(_("E156: Missing sign name"));
else
{
/* Isolate the sign name. If it's a number skip leading zeroes,
* so that "099" and "99" are the same sign. But keep "0". */
p = skiptowhite(arg);
if (*p != NUL)
*p++ = NUL;
while (arg[0] == '0' && arg[1] != NUL)
++arg;
sp_prev = NULL;
for (sp = first_sign; sp != NULL; sp = sp->sn_next)
{
if (STRCMP(sp->sn_name, arg) == 0)
break;
sp_prev = sp;
}
if (idx == SIGNCMD_DEFINE)
{
/* ":sign define {name} ...": define a sign */
if (sp == NULL)
{
sign_T *lp;
int start = next_sign_typenr;
/* Allocate a new sign. */
sp = xcalloc(1, sizeof(sign_T));
/* Check that next_sign_typenr is not already being used.
* This only happens after wrapping around. Hopefully
* another one got deleted and we can use its number. */
for (lp = first_sign; lp != NULL; )
{
if (lp->sn_typenr == next_sign_typenr)
{
++next_sign_typenr;
if (next_sign_typenr == MAX_TYPENR)
next_sign_typenr = 1;
if (next_sign_typenr == start)
{
xfree(sp);
EMSG(_("E612: Too many signs defined"));
return;
}
lp = first_sign; /* start all over */
continue;
}
lp = lp->sn_next;
}
sp->sn_typenr = next_sign_typenr;
if (++next_sign_typenr == MAX_TYPENR)
next_sign_typenr = 1; /* wrap around */
sp->sn_name = vim_strsave(arg);
/* add the new sign to the list of signs */
if (sp_prev == NULL)
first_sign = sp;
else
sp_prev->sn_next = sp;
}
/* set values for a defined sign. */
for (;;)
{
arg = skipwhite(p);
if (*arg == NUL)
break;
p = skiptowhite_esc(arg);
if (STRNCMP(arg, "icon=", 5) == 0)
{
arg += 5;
xfree(sp->sn_icon);
sp->sn_icon = vim_strnsave(arg, (int)(p - arg));
backslash_halve(sp->sn_icon);
}
else if (STRNCMP(arg, "text=", 5) == 0)
{
char_u *s;
int cells;
int len;
arg += 5;
/* Count cells and check for non-printable chars */
if (has_mbyte)
{
cells = 0;
for (s = arg; s < p; s += (*mb_ptr2len)(s))
{
if (!vim_isprintc((*mb_ptr2char)(s)))
break;
cells += (*mb_ptr2cells)(s);
}
}
else
{
for (s = arg; s < p; ++s)
if (!vim_isprintc(*s))
break;
cells = (int)(s - arg);
}
/* Currently must be one or two display cells */
if (s != p || cells < 1 || cells > 2)
{
*p = NUL;
EMSG2(_("E239: Invalid sign text: %s"), arg);
return;
}
xfree(sp->sn_text);
/* Allocate one byte more if we need to pad up
* with a space. */
len = (int)(p - arg + ((cells == 1) ? 1 : 0));
sp->sn_text = vim_strnsave(arg, len);
if (cells == 1)
STRCPY(sp->sn_text + len - 1, " ");
}
else if (STRNCMP(arg, "linehl=", 7) == 0)
{
arg += 7;
sp->sn_line_hl = syn_check_group(arg, (int)(p - arg));
}
else if (STRNCMP(arg, "texthl=", 7) == 0)
{
arg += 7;
sp->sn_text_hl = syn_check_group(arg, (int)(p - arg));
}
else
{
EMSG2(_(e_invarg2), arg);
return;
}
}
}
else if (sp == NULL)
EMSG2(_("E155: Unknown sign: %s"), arg);
else if (idx == SIGNCMD_LIST)
/* ":sign list {name}" */
sign_list_defined(sp);
else
/* ":sign undefine {name}" */
sign_undefine(sp, sp_prev);
}
if (*arg == NUL) {
if (idx == SIGNCMD_PLACE) {
// ":sign place": list placed signs in all buffers
sign_list_placed(NULL);
} else if (idx == SIGNCMD_UNPLACE) {
// ":sign unplace": remove placed sign at cursor
id = buf_findsign_id(curwin->w_buffer, curwin->w_cursor.lnum);
if (id > 0) {
buf_delsign(curwin->w_buffer, id);
update_debug_sign(curwin->w_buffer, curwin->w_cursor.lnum);
} else {
EMSG(_("E159: Missing sign number"));
}
} else {
EMSG(_(e_argreq));
}
return;
}
else
{
int id = -1;
linenr_T lnum = -1;
char_u *sign_name = NULL;
char_u *arg1;
if (*arg == NUL)
{
if (idx == SIGNCMD_PLACE)
{
/* ":sign place": list placed signs in all buffers */
sign_list_placed(NULL);
}
else if (idx == SIGNCMD_UNPLACE)
{
/* ":sign unplace": remove placed sign at cursor */
id = buf_findsign_id(curwin->w_buffer, curwin->w_cursor.lnum);
if (id > 0)
{
buf_delsign(curwin->w_buffer, id);
update_debug_sign(curwin->w_buffer, curwin->w_cursor.lnum);
}
else
EMSG(_("E159: Missing sign number"));
}
else
EMSG(_(e_argreq));
return;
}
if (idx == SIGNCMD_UNPLACE && arg[0] == '*' && arg[1] == NUL)
{
/* ":sign unplace *": remove all placed signs */
buf_delete_all_signs();
return;
}
/* first arg could be placed sign id */
arg1 = arg;
if (ascii_isdigit(*arg))
{
id = getdigits_int(&arg);
if (!ascii_iswhite(*arg) && *arg != NUL)
{
id = -1;
arg = arg1;
}
else
{
arg = skipwhite(arg);
if (idx == SIGNCMD_UNPLACE && *arg == NUL)
{
// ":sign unplace {id}": remove placed sign by number
FOR_ALL_BUFFERS(buf) {
if ((lnum = buf_delsign(buf, id)) != 0) {
update_debug_sign(buf, lnum);
}
}
return;
}
}
}
/*
* Check for line={lnum} name={name} and file={fname} or buffer={nr}.
* Leave "arg" pointing to {fname}.
*/
buf_T *buf = NULL;
for (;;)
{
if (STRNCMP(arg, "line=", 5) == 0)
{
arg += 5;
lnum = atoi((char *)arg);
arg = skiptowhite(arg);
}
else if (STRNCMP(arg, "*", 1) == 0 && idx == SIGNCMD_UNPLACE)
{
if (id != -1)
{
EMSG(_(e_invarg));
return;
}
id = -2;
arg = skiptowhite(arg + 1);
}
else if (STRNCMP(arg, "name=", 5) == 0)
{
arg += 5;
sign_name = arg;
arg = skiptowhite(arg);
if (*arg != NUL)
*arg++ = NUL;
while (sign_name[0] == '0' && sign_name[1] != NUL)
++sign_name;
}
else if (STRNCMP(arg, "file=", 5) == 0)
{
arg += 5;
buf = buflist_findname(arg);
break;
}
else if (STRNCMP(arg, "buffer=", 7) == 0)
{
arg += 7;
buf = buflist_findnr(getdigits_int(&arg));
if (*skipwhite(arg) != NUL)
EMSG(_(e_trailing));
break;
}
else
{
EMSG(_(e_invarg));
return;
}
arg = skipwhite(arg);
}
if (buf == NULL)
{
EMSG2(_("E158: Invalid buffer name: %s"), arg);
}
else if (id <= 0 && !(idx == SIGNCMD_UNPLACE && id == -2))
{
if (lnum >= 0 || sign_name != NULL)
EMSG(_(e_invarg));
else
/* ":sign place file={fname}": list placed signs in one file */
sign_list_placed(buf);
}
else if (idx == SIGNCMD_JUMP)
{
/* ":sign jump {id} file={fname}" */
if (lnum >= 0 || sign_name != NULL)
EMSG(_(e_invarg));
else if ((lnum = buf_findsign(buf, id)) > 0)
{ /* goto a sign ... */
if (buf_jump_open_win(buf) != NULL)
{ /* ... in a current window */
curwin->w_cursor.lnum = lnum;
check_cursor_lnum();
beginline(BL_WHITE);
}
else
{ // ... not currently in a window
char *cmd = xmalloc(STRLEN(buf->b_fname) + 25);
sprintf(cmd, "e +%" PRId64 " %s",
(int64_t)lnum, buf->b_fname);
do_cmdline_cmd(cmd);
xfree(cmd);
}
foldOpenCursor();
}
else
EMSGN(_("E157: Invalid sign ID: %" PRId64), id);
}
else if (idx == SIGNCMD_UNPLACE)
{
if (lnum >= 0 || sign_name != NULL)
EMSG(_(e_invarg));
else if (id == -2)
{
/* ":sign unplace * file={fname}" */
redraw_buf_later(buf, NOT_VALID);
buf_delete_signs(buf);
}
else
{
/* ":sign unplace {id} file={fname}" */
lnum = buf_delsign(buf, id);
update_debug_sign(buf, lnum);
}
}
/* idx == SIGNCMD_PLACE */
else if (sign_name != NULL)
{
for (sp = first_sign; sp != NULL; sp = sp->sn_next)
if (STRCMP(sp->sn_name, sign_name) == 0)
break;
if (sp == NULL)
{
EMSG2(_("E155: Unknown sign: %s"), sign_name);
return;
}
if (lnum > 0)
/* ":sign place {id} line={lnum} name={name} file={fname}":
* place a sign */
buf_addsign(buf, id, lnum, sp->sn_typenr);
else
/* ":sign place {id} file={fname}": change sign type */
lnum = buf_change_sign_type(buf, id, sp->sn_typenr);
if (lnum > 0)
update_debug_sign(buf, lnum);
else
EMSG2(_("E885: Not possible to change sign %s"), sign_name);
}
else
EMSG(_(e_invarg));
if (idx == SIGNCMD_UNPLACE && arg[0] == '*' && arg[1] == NUL) {
// ":sign unplace *": remove all placed signs
buf_delete_all_signs();
return;
}
// first arg could be placed sign id
arg1 = arg;
if (ascii_isdigit(*arg)) {
id = getdigits_int(&arg);
if (!ascii_iswhite(*arg) && *arg != NUL) {
id = -1;
arg = arg1;
} else {
arg = skipwhite(arg);
if (idx == SIGNCMD_UNPLACE && *arg == NUL) {
// ":sign unplace {id}": remove placed sign by number
FOR_ALL_BUFFERS(buf) {
if ((lnum = buf_delsign(buf, id)) != 0) {
update_debug_sign(buf, lnum);
}
}
return;
}
}
}
// Check for line={lnum} name={name} and file={fname} or buffer={nr}.
// Leave "arg" pointing to {fname}.
buf_T *buf = NULL;
for (;;) {
if (STRNCMP(arg, "line=", 5) == 0) {
arg += 5;
lnum = atoi((char *)arg);
arg = skiptowhite(arg);
} else if (STRNCMP(arg, "*", 1) == 0 && idx == SIGNCMD_UNPLACE) {
if (id != -1) {
EMSG(_(e_invarg));
return;
}
id = -2;
arg = skiptowhite(arg + 1);
} else if (STRNCMP(arg, "name=", 5) == 0) {
arg += 5;
sign_name = arg;
arg = skiptowhite(arg);
if (*arg != NUL) {
*arg++ = NUL;
}
while (sign_name[0] == '0' && sign_name[1] != NUL) {
sign_name++;
}
} else if (STRNCMP(arg, "file=", 5) == 0) {
arg += 5;
buf = buflist_findname(arg);
break;
} else if (STRNCMP(arg, "buffer=", 7) == 0) {
arg += 7;
buf = buflist_findnr(getdigits_int(&arg));
if (*skipwhite(arg) != NUL) {
EMSG(_(e_trailing));
}
break;
} else {
EMSG(_(e_invarg));
return;
}
arg = skipwhite(arg);
}
if (buf == NULL) {
EMSG2(_("E158: Invalid buffer name: %s"), arg);
} else if (id <= 0 && !(idx == SIGNCMD_UNPLACE && id == -2)) {
if (lnum >= 0 || sign_name != NULL) {
EMSG(_(e_invarg));
} else {
// ":sign place file={fname}": list placed signs in one file
sign_list_placed(buf);
}
} else if (idx == SIGNCMD_JUMP) {
// ":sign jump {id} file={fname}"
if (lnum >= 0 || sign_name != NULL) {
EMSG(_(e_invarg));
} else if ((lnum = buf_findsign(buf, id)) > 0) {
// goto a sign ...
if (buf_jump_open_win(buf) != NULL) {
// ... in a current window
curwin->w_cursor.lnum = lnum;
check_cursor_lnum();
beginline(BL_WHITE);
} else {
// ... not currently in a window
if (buf->b_fname == NULL) {
EMSG(_("E934: Cannot jump to a buffer that does not have a name"));
return;
}
size_t cmdlen = STRLEN(buf->b_fname) + 24;
char *cmd = xmallocz(cmdlen);
snprintf(cmd, cmdlen, "e +%" PRId64 " %s",
(int64_t)lnum, buf->b_fname);
do_cmdline_cmd(cmd);
xfree(cmd);
}
foldOpenCursor();
} else {
EMSGN(_("E157: Invalid sign ID: %" PRId64), id);
}
} else if (idx == SIGNCMD_UNPLACE) {
if (lnum >= 0 || sign_name != NULL) {
EMSG(_(e_invarg));
} else if (id == -2) {
// ":sign unplace * file={fname}"
redraw_buf_later(buf, NOT_VALID);
buf_delete_signs(buf);
} else {
// ":sign unplace {id} file={fname}"
lnum = buf_delsign(buf, id);
update_debug_sign(buf, lnum);
}
} else if (sign_name != NULL) {
// idx == SIGNCMD_PLACE
for (sp = first_sign; sp != NULL; sp = sp->sn_next) {
if (STRCMP(sp->sn_name, sign_name) == 0) {
break;
}
}
if (sp == NULL) {
EMSG2(_("E155: Unknown sign: %s"), sign_name);
return;
}
if (lnum > 0) {
// ":sign place {id} line={lnum} name={name} file={fname}":
// place a sign
buf_addsign(buf, id, lnum, sp->sn_typenr);
} else {
// ":sign place {id} file={fname}": change sign type
lnum = buf_change_sign_type(buf, id, sp->sn_typenr);
}
if (lnum > 0) {
update_debug_sign(buf, lnum);
} else {
EMSG2(_("E885: Not possible to change sign %s"), sign_name);
}
} else {
EMSG(_(e_invarg));
}
}
}
/*

View File

@@ -24,6 +24,7 @@
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/misc1.h"
#include "nvim/option.h"
#include "nvim/popupmnu.h"
#include "nvim/screen.h"
#include "nvim/strings.h"
@@ -669,8 +670,7 @@ int win_col_off(win_T *wp)
return ((wp->w_p_nu || wp->w_p_rnu) ? number_width(wp) + 1 : 0)
+ (cmdwin_type == 0 || wp != curwin ? 0 : 1)
+ (int)wp->w_p_fdc
+ (wp->w_buffer->b_signlist != NULL ? 2 : 0)
;
+ (signcolumn_on(wp) ? 2 : 0);
}
int curwin_col_off(void)

View File

@@ -289,6 +289,7 @@ static char *(p_fcl_values[]) = { "all", NULL };
static char *(p_cot_values[]) = { "menu", "menuone", "longest", "preview",
"noinsert", "noselect", NULL };
static char *(p_icm_values[]) = { "nosplit", "split", NULL };
static char *(p_scl_values[]) = { "yes", "no", "auto", NULL };
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "option.c.generated.h"
@@ -3007,6 +3008,11 @@ did_set_string_option (
} else {
completeopt_was_set();
}
} else if (varp == &curwin->w_p_scl) {
// 'signcolumn'
if (check_opt_strings(*varp, p_scl_values, false) != OK) {
errmsg = e_invarg;
}
}
/* 'pastetoggle': translate key codes like in a mapping */
else if (varp == &p_pt) {
@@ -4782,7 +4788,6 @@ static int find_key_option(const char_u *arg)
return find_key_option_len(arg, STRLEN(arg));
}
/*
* if 'all' == 0: show changed options
* if 'all' == 1: show all normal options
@@ -5428,6 +5433,7 @@ static char_u *get_varp(vimoption_T *p)
case PV_UDF: return (char_u *)&(curbuf->b_p_udf);
case PV_WM: return (char_u *)&(curbuf->b_p_wm);
case PV_KMAP: return (char_u *)&(curbuf->b_p_keymap);
case PV_SCL: return (char_u *)&(curwin->w_p_scl);
default: EMSG(_("E356: get_varp ERROR"));
}
/* always return a valid pointer to avoid a crash! */
@@ -5505,7 +5511,8 @@ void copy_winopt(winopt_T *from, winopt_T *to)
to->wo_fde = vim_strsave(from->wo_fde);
to->wo_fdt = vim_strsave(from->wo_fdt);
to->wo_fmr = vim_strsave(from->wo_fmr);
check_winopt(to); /* don't want NULL pointers */
to->wo_scl = vim_strsave(from->wo_scl);
check_winopt(to); // don't want NULL pointers
}
/*
@@ -5528,6 +5535,7 @@ static void check_winopt(winopt_T *wop)
check_string_option(&wop->wo_fde);
check_string_option(&wop->wo_fdt);
check_string_option(&wop->wo_fmr);
check_string_option(&wop->wo_scl);
check_string_option(&wop->wo_rlc);
check_string_option(&wop->wo_stl);
check_string_option(&wop->wo_cc);
@@ -5546,6 +5554,7 @@ void clear_winopt(winopt_T *wop)
clear_string_option(&wop->wo_fde);
clear_string_option(&wop->wo_fdt);
clear_string_option(&wop->wo_fmr);
clear_string_option(&wop->wo_scl);
clear_string_option(&wop->wo_rlc);
clear_string_option(&wop->wo_stl);
clear_string_option(&wop->wo_cc);
@@ -6902,3 +6911,39 @@ int csh_like_shell(void)
return strstr((char *)path_tail(p_sh), "csh") != NULL;
}
/// Return true when window "wp" has a column to draw signs in.
bool signcolumn_on(win_T *wp)
{
if (*wp->w_p_scl == 'n') {
return false;
}
if (*wp->w_p_scl == 'y') {
return true;
}
return wp->w_buffer->b_signlist != NULL;
}
/// Get window or buffer local options.
dict_T * get_winbuf_options(int bufopt)
{
dict_T *d = dict_alloc();
for (int opt_idx = 0; options[opt_idx].fullname; opt_idx++) {
struct vimoption *opt = &options[opt_idx];
if ((bufopt && (opt->indir & PV_BUF))
|| (!bufopt && (opt->indir & PV_WIN))) {
char_u *varp = get_varp(opt);
if (varp != NULL) {
if (opt->flags & P_STRING) {
dict_add_nr_str(d, opt->fullname, 0L, *(char_u **)varp);
} else {
dict_add_nr_str(d, opt->fullname, *varp, NULL);
}
}
}
}
return d;
}

View File

@@ -799,7 +799,8 @@ enum {
, WV_WFH
, WV_WFW
, WV_WRAP
, WV_COUNT /* must be the last one */
, WV_SCL
, WV_COUNT // must be the last one
};
/* Value for b_p_ul indicating the global value must be used. */

View File

@@ -2169,6 +2169,14 @@ return {
varname='p_siso',
defaults={if_true={vi=0}}
},
{
full_name='signcolumn', abbreviation='scl',
type='string', scope={'window'},
vi_def=true,
alloced=true,
redraw={'current_window'},
defaults={if_true={vi="auto"}}
},
{
full_name='smartcase', abbreviation='scs',
type='bool', scope={'global'},

View File

@@ -580,15 +580,6 @@ void update_debug_sign(buf_T *buf, linenr_T lnum)
update_finish();
}
/*
* Return TRUE when window "wp" has a column to draw signs in.
*/
static int draw_signcolumn(win_T *wp)
{
return (wp->w_buffer->b_signlist != NULL);
}
/*
* Update a single window.
*
@@ -1603,7 +1594,7 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h
' ', ' ', hl_attr(HLF_FC));
}
if (draw_signcolumn(wp)) {
if (signcolumn_on(wp)) {
int nn = n + 2;
/* draw the sign column left of the fold column */
@@ -1644,8 +1635,7 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h
n = nn;
}
if (draw_signcolumn(wp))
{
if (signcolumn_on(wp)) {
int nn = n + 2;
/* draw the sign column after the fold column */
@@ -1757,8 +1747,8 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
* text */
RL_MEMSET(col, hl_attr(HLF_FL), wp->w_width - col);
/* If signs are being displayed, add two spaces. */
if (draw_signcolumn(wp)) {
// If signs are being displayed, add two spaces.
if (signcolumn_on(wp)) {
len = wp->w_width - col;
if (len > 0) {
if (len > 2) {
@@ -2706,7 +2696,7 @@ win_line (
draw_state = WL_SIGN;
/* Show the sign column when there are any signs in this
* buffer or when using Netbeans. */
if (draw_signcolumn(wp)) {
if (signcolumn_on(wp)) {
int text_sign;
/* Draw two cells with the sign value or blank. */
c_extra = ' ';

View File

@@ -30,6 +30,7 @@ SCRIPTS := \
# Tests using runtest.vim.vim.
# Keep test_alot*.res as the last one, sort the others.
NEW_TESTS = \
test_bufwintabinfo.res \
test_cmdline.res \
test_cscope.res \
test_diffmode.res \
@@ -40,6 +41,7 @@ NEW_TESTS = \
test_match.res \
test_matchadd_conceal.res \
test_quickfix.res \
test_signs.res \
test_syntax.res \
test_usercommands.res \
test_timers.res \

View File

@@ -86,6 +86,12 @@ function RunTheTest(test)
if exists("*TearDown")
call TearDown()
endif
" Close any extra windows and make the current one not modified.
while winnr('$') > 1
bwipe!
endwhile
set nomodified
endfunc
" Source the test script. First grab the file name, in case the script

View File

@@ -0,0 +1,103 @@
" 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')[0].name)
call assert_equal([], getbufinfo(2016))
edit Xtestfile1
hide edit Xtestfile2
hide enew
call assert_equal(3, len(getbufinfo({'bufloaded':1})))
set tabstop&vim
let b:editor = 'vim'
let l = getbufinfo('%')
call assert_equal(bufnr('%'), l[0].bufnr)
call assert_equal('vim', l[0].variables.editor)
call assert_notequal(-1, index(l[0].windows, bufwinid('%')))
if has('signs')
call append(0, ['Linux', 'Windows', 'Mac'])
sign define Mark text=>> texthl=Search
exe "sign place 2 line=3 name=Mark buffer=" . bufnr('%')
let l = getbufinfo('%')
call assert_equal(2, l[0].signs[0].id)
call assert_equal(3, l[0].signs[0].lnum)
call assert_equal('Mark', l[0].signs[0].name)
sign unplace *
sign undefine Mark
enew!
endif
only
let w1_id = win_getid()
new
let w2_id = win_getid()
tabnew | let w3_id = win_getid()
new | let w4_id = win_getid()
new | let w5_id = win_getid()
call setwinvar(0, 'signal', 'green')
tabfirst
let winlist = getwininfo()
call assert_equal(5, len(winlist))
call assert_equal(winbufnr(2), winlist[1].bufnr)
call assert_equal(winheight(2), winlist[1].height)
call assert_equal(1, winlist[2].winnr)
call assert_equal(2, winlist[3].tabnr)
call assert_equal('green', winlist[2].variables.signal)
call assert_equal(winwidth(1), winlist[0].width)
call assert_equal(w4_id, winlist[3].winid)
let winfo = getwininfo(w5_id)[0]
call assert_equal(2, winfo.tabnr)
call assert_equal([], getwininfo(3))
call settabvar(1, 'space', 'build')
let tablist = gettabinfo()
call assert_equal(2, len(tablist))
call assert_equal(3, len(tablist[1].windows))
call assert_equal(2, tablist[1].tabnr)
call assert_equal('build', tablist[0].variables.space)
call assert_equal(w2_id, tablist[0].windows[0])
call assert_equal([], gettabinfo(3))
tabonly | only
lexpr ''
lopen
copen
let winlist = getwininfo()
call assert_false(winlist[0].quickfix)
call assert_false(winlist[0].loclist)
call assert_true(winlist[1].quickfix)
call assert_true(winlist[1].loclist)
call assert_true(winlist[2].quickfix)
call assert_false(winlist[2].loclist)
wincmd t | only
endfunction
function Test_get_buf_options()
let opts = getbufvar(bufnr('%'), '&')
call assert_equal(v:t_dict, type(opts))
call assert_equal(8, opts.tabstop)
endfunc
function Test_get_win_options()
let opts = getwinvar(1, '&')
call assert_equal(v:t_dict, type(opts))
call assert_equal(0, opts.linebreak)
if has('signs')
call assert_equal('auto', opts.signcolumn)
endif
let opts = gettabwinvar(1, 1, '&')
call assert_equal(v:t_dict, type(opts))
call assert_equal(0, opts.linebreak)
if has('signs')
call assert_equal('auto', opts.signcolumn)
endif
endfunc

View File

@@ -0,0 +1,199 @@
" Test for signs
if !has('signs')
finish
endif
func Test_sign()
new
call setline(1, ['a', 'b', 'c', 'd'])
" Define some signs.
" We can specify icons even if not all versions of vim support icons as
" icon is ignored when not supported. "(not supported)" is shown after
" the icon name when listing signs.
sign define Sign1 text=x
try
sign define Sign2 text=xy texthl=Title linehl=Error icon=../../pixmaps/stock_vim_find_help.png
catch /E255:/
" ignore error: E255: Couldn't read in sign data!
" This error can happen when running in gui.
" Some gui like Motif do not support the png icon format.
endtry
" Test listing signs.
let a=execute('sign list')
call assert_match("^\nsign Sign1 text=x \nsign Sign2 icon=../../pixmaps/stock_vim_find_help.png .*text=xy linehl=Error texthl=Title$", a)
let a=execute('sign list Sign1')
call assert_equal("\nsign Sign1 text=x ", a)
" Split the window to the bottom to verify sign jump will stay in the current window
" if the buffer is displayed there.
let bn = bufnr('%')
let wn = winnr()
exe 'sign place 41 line=3 name=Sign1 buffer=' . bn
1
bot split
exe 'sign jump 41 buffer=' . bufnr('%')
call assert_equal('c', getline('.'))
call assert_equal(3, winnr())
call assert_equal(bn, bufnr('%'))
call assert_notequal(wn, winnr())
" Create a new buffer and check that ":sign jump" switches to the old buffer.
1
new foo
call assert_notequal(bn, bufnr('%'))
exe 'sign jump 41 buffer=' . bn
call assert_equal(bn, bufnr('%'))
call assert_equal('c', getline('.'))
" Redraw to make sure that screen redraw with sign gets exercised,
" with and without 'rightleft'.
if has('rightleft')
set rightleft
redraw
set norightleft
endif
redraw
" Check that we can't change sign.
call assert_fails("exe 'sign place 40 name=Sign1 buffer=' . bufnr('%')", 'E885:')
" Check placed signs
let a=execute('sign place')
call assert_equal("\n--- Signs ---\nSigns for [NULL]:\n line=3 id=41 name=Sign1\n", a)
" Unplace the sign and try jumping to it again should fail.
sign unplace 41
1
call assert_fails("exe 'sign jump 41 buffer=' . bufnr('%')", 'E157:')
call assert_equal('a', getline('.'))
" Unplace sign on current line.
exe 'sign place 42 line=4 name=Sign2 buffer=' . bufnr('%')
4
sign unplace
let a=execute('sign place')
call assert_equal("\n--- Signs ---\n", a)
" Try again to unplace sign on current line, it should fail this time.
call assert_fails('sign unplace', 'E159:')
" Unplace all signs.
exe 'sign place 41 line=3 name=Sign1 buffer=' . bufnr('%')
sign unplace *
let a=execute('sign place')
call assert_equal("\n--- Signs ---\n", a)
" Check :jump with file=...
edit foo
call setline(1, ['A', 'B', 'C', 'D'])
try
sign define Sign3 text=y texthl=DoesNotExist linehl=DoesNotExist icon=doesnotexist.xpm
catch /E255:/
" ignore error: E255: it can happens for guis.
endtry
let fn = expand('%:p')
exe 'sign place 43 line=2 name=Sign3 file=' . fn
edit bar
call assert_notequal(fn, expand('%:p'))
exe 'sign jump 43 file=' . fn
call assert_equal('B', getline('.'))
" After undefining the sign, we should no longer be able to place it.
sign undefine Sign1
sign undefine Sign2
sign undefine Sign3
call assert_fails("exe 'sign place 41 line=3 name=Sign1 buffer=' . bufnr('%')", 'E155:')
endfunc
" Undefining placed sign is not recommended.
" Quoting :help sign
"
" :sign undefine {name}
" Deletes a previously defined sign. If signs with this {name}
" are still placed this will cause trouble.
func Test_sign_undefine_still_placed()
new foobar
sign define Sign text=x
exe 'sign place 41 line=1 name=Sign buffer=' . bufnr('%')
sign undefine Sign
" Listing placed sign should show that sign is deleted.
let a=execute('sign place')
call assert_equal("\n--- Signs ---\nSigns for foobar:\n line=1 id=41 name=[Deleted]\n", a)
sign unplace 41
let a=execute('sign place')
call assert_equal("\n--- Signs ---\n", a)
endfunc
func Test_sign_completion()
sign define Sign1 text=x
sign define Sign2 text=y
call feedkeys(":sign \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign define jump list place undefine unplace', @:)
call feedkeys(":sign define Sign \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign define Sign icon= linehl= text= texthl=', @:)
call feedkeys(":sign define Sign linehl=Spell\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign define Sign linehl=SpellBad SpellCap SpellLocal SpellRare', @:)
call writefile(['foo'], 'XsignOne')
call writefile(['bar'], 'XsignTwo')
call feedkeys(":sign define Sign icon=Xsig\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign define Sign icon=XsignOne XsignTwo', @:)
call delete('XsignOne')
call delete('XsignTwo')
call feedkeys(":sign undefine \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign undefine Sign1 Sign2', @:)
call feedkeys(":sign place 1 \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign place 1 buffer= file= line= name=', @:)
call feedkeys(":sign place 1 name=\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign place 1 name=Sign1 Sign2', @:)
call feedkeys(":sign unplace 1 \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign unplace 1 buffer= file=', @:)
call feedkeys(":sign list \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign list Sign1 Sign2', @:)
call feedkeys(":sign jump 1 \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign jump 1 buffer= file=', @:)
sign undefine Sign1
sign undefine Sign2
endfunc
func Test_sign_invalid_commands()
call assert_fails('sign', 'E471:')
call assert_fails('sign jump', 'E471:')
call assert_fails('sign xxx', 'E160:')
call assert_fails('sign define', 'E156:')
call assert_fails('sign define Sign1 xxx', 'E475:')
call assert_fails('sign undefine', 'E156:')
call assert_fails('sign list xxx', 'E155:')
call assert_fails('sign place 1 buffer=', 'E158:')
call assert_fails('sign define Sign2 text=', 'E239:')
endfunc
func Test_sign_delete_buffer()
new
sign define Sign text=x
let bufnr = bufnr('%')
new
exe 'bd ' . bufnr
exe 'sign place 61 line=3 name=Sign buffer=' . bufnr
call assert_fails('sign jump 61 buffer=' . bufnr, 'E934:')
sign unplace 61
sign undefine Sign
endfunc

View File

@@ -146,7 +146,7 @@ static int included_patches[] = {
// 2297 NA
// 2296,
// 2295,
// 2294,
2294,
// 2293,
// 2292,
// 2291,
@@ -163,12 +163,12 @@ static int included_patches[] = {
// 2280,
// 2279,
// 2278 NA
// 2277,
2277,
// 2276,
// 2275,
2274,
// 2273,
// 2272,
2273,
2272,
// 2271 NA
// 2270 NA
// 2269,
@@ -214,8 +214,8 @@ static int included_patches[] = {
// 2229,
// 2228,
2227,
// 2226,
// 2225,
2226,
2225,
// 2224,
// 2223,
// 2222,
@@ -225,7 +225,7 @@ static int included_patches[] = {
// 2218 NA
2217,
// 2216 NA
// 2215,
2215,
// 2214 NA
2213,
2212,
@@ -236,17 +236,17 @@ static int included_patches[] = {
// 2207 NA
// 2206 NA
2205,
// 2204,
2204,
// 2203 NA
// 2202 NA
// 2201,
2201,
// 2200,
// 2199 NA
// 2198,
// 2197,
// 2196,
// 2195 NA
// 2194,
2194,
// 2193 NA
// 2192 NA
// 2191 NA
@@ -257,7 +257,7 @@ static int included_patches[] = {
// 2186 NA
// 2185,
// 2184,
// 2183,
2183,
// 2182 NA
// 2181,
// 2180,

View File

@@ -5797,6 +5797,19 @@ void win_id2tabwin(typval_T *argvars, list_T *list)
list_append_number(list, winnr);
}
win_T * win_id2wp(typval_T *argvars)
{
int id = get_tv_number(&argvars[0]);
FOR_ALL_TAB_WINDOWS(tp, wp) {
if (wp->handle == id) {
return wp;
}
}
return NULL;
}
int win_id2win(typval_T *argvars)
{
win_T *wp;