diff options
| author | James McCoy <jamessan@jamessan.com> | 2017-01-01 15:12:33 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-01-01 15:12:33 -0500 |
| commit | c5f4b92ff93a40ec4e77b78d0576903e7a60eefd (patch) | |
| tree | d4bdbc55eec66541aa95a03adff0403d6ab71685 /src/nvim | |
| parent | 57ce8b56488a781088cb503f0da723f59e2f9554 (diff) | |
| parent | 46235a30edc4ee09fdbd4f489865982bafde247d (diff) | |
| download | rneovim-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.h | 2 | ||||
| -rw-r--r-- | src/nvim/edit.c | 2 | ||||
| -rw-r--r-- | src/nvim/eval.c | 274 | ||||
| -rw-r--r-- | src/nvim/eval.lua | 3 | ||||
| -rw-r--r-- | src/nvim/ex_cmds.c | 695 | ||||
| -rw-r--r-- | src/nvim/move.c | 4 | ||||
| -rw-r--r-- | src/nvim/option.c | 49 | ||||
| -rw-r--r-- | src/nvim/option_defs.h | 3 | ||||
| -rw-r--r-- | src/nvim/options.lua | 8 | ||||
| -rw-r--r-- | src/nvim/screen.c | 20 | ||||
| -rw-r--r-- | src/nvim/testdir/Makefile | 2 | ||||
| -rw-r--r-- | src/nvim/testdir/runtest.vim | 6 | ||||
| -rw-r--r-- | src/nvim/testdir/test_bufwintabinfo.vim | 103 | ||||
| -rw-r--r-- | src/nvim/testdir/test_signs.vim | 199 | ||||
| -rw-r--r-- | src/nvim/version.c | 22 | ||||
| -rw-r--r-- | src/nvim/window.c | 13 |
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 |