aboutsummaryrefslogtreecommitdiff
path: root/src/nvim
diff options
context:
space:
mode:
authorJames McCoy <jamessan@jamessan.com>2017-01-01 15:12:33 -0500
committerGitHub <noreply@github.com>2017-01-01 15:12:33 -0500
commitc5f4b92ff93a40ec4e77b78d0576903e7a60eefd (patch)
treed4bdbc55eec66541aa95a03adff0403d6ab71685 /src/nvim
parent57ce8b56488a781088cb503f0da723f59e2f9554 (diff)
parent46235a30edc4ee09fdbd4f489865982bafde247d (diff)
downloadrneovim-c5f4b92ff93a40ec4e77b78d0576903e7a60eefd.tar.gz
rneovim-c5f4b92ff93a40ec4e77b78d0576903e7a60eefd.tar.bz2
rneovim-c5f4b92ff93a40ec4e77b78d0576903e7a60eefd.zip
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
Diffstat (limited to 'src/nvim')
-rw-r--r--src/nvim/buffer_defs.h2
-rw-r--r--src/nvim/edit.c2
-rw-r--r--src/nvim/eval.c274
-rw-r--r--src/nvim/eval.lua3
-rw-r--r--src/nvim/ex_cmds.c695
-rw-r--r--src/nvim/move.c4
-rw-r--r--src/nvim/option.c49
-rw-r--r--src/nvim/option_defs.h3
-rw-r--r--src/nvim/options.lua8
-rw-r--r--src/nvim/screen.c20
-rw-r--r--src/nvim/testdir/Makefile2
-rw-r--r--src/nvim/testdir/runtest.vim6
-rw-r--r--src/nvim/testdir/test_bufwintabinfo.vim103
-rw-r--r--src/nvim/testdir/test_signs.vim199
-rw-r--r--src/nvim/version.c22
-rw-r--r--src/nvim/window.c13
16 files changed, 993 insertions, 412 deletions
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 0418a737eb..2b66a07f48 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -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
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 7e917336e5..bb946337b5 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -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;
}
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index bdbd77337d..32e1991742 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -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 {
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index a0671cac1f..980a8d2326 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -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}},
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 73a1ab7723..fcaf17a0fc 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -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;
-
- /* Parse the subcommand. */
- p = skiptowhite(arg);
- idx = sign_cmd_idx(arg, p);
- if (idx == SIGNCMD_LAST)
- {
- EMSG2(_("E160: Unknown sign command: %s"), arg);
- return;
+ 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;
+ }
+ 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);
+ }
+ }
+ } 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;
}
- 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 */
- 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 (idx == SIGNCMD_UNPLACE && arg[0] == '*' && arg[1] == NUL) {
+ // ":sign unplace *": remove all placed signs
+ buf_delete_all_signs();
+ 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));
+
+ // 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