diff options
Diffstat (limited to 'src/nvim/ex_cmds.c')
-rw-r--r-- | src/nvim/ex_cmds.c | 1150 |
1 files changed, 0 insertions, 1150 deletions
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 212aeb4c27..8722c03204 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -67,10 +67,6 @@ #include "nvim/os/input.h" #include "nvim/os/time.h" -/* - * Struct to hold the sign properties. - */ -typedef struct sign sign_T; /// Case matching style to use for :substitute typedef enum { @@ -5521,21 +5517,6 @@ void ex_helptags(exarg_T *eap) } } -struct sign -{ - sign_T *sn_next; // next sign in list - int sn_typenr; // type number of sign - char_u *sn_name; // name of sign - char_u *sn_icon; // name of pixmap - char_u *sn_text; // text used instead of pixmap - int sn_line_hl; // highlight ID for line - int sn_text_hl; // highlight ID for text - int sn_num_hl; // highlight ID for line number -}; - -static sign_T *first_sign = NULL; -static int next_sign_typenr = 1; - /* * ":helpclose": Close one help window */ @@ -5549,1137 +5530,6 @@ void ex_helpclose(exarg_T *eap) } } -static char *cmds[] = { - "define", -#define SIGNCMD_DEFINE 0 - "undefine", -#define SIGNCMD_UNDEFINE 1 - "list", -#define SIGNCMD_LIST 2 - "place", -#define SIGNCMD_PLACE 3 - "unplace", -#define SIGNCMD_UNPLACE 4 - "jump", -#define SIGNCMD_JUMP 5 - NULL -#define SIGNCMD_LAST 6 -}; - -/* - * Find index of a ":sign" subcmd from its name. - * "*end_cmd" must be writable. - */ -static int sign_cmd_idx( - char_u *begin_cmd, /* begin of sign subcmd */ - char_u *end_cmd /* just after sign subcmd */ - ) -{ - int idx; - char save = *end_cmd; - - *end_cmd = NUL; - for (idx = 0; ; ++idx) { - if (cmds[idx] == NULL || STRCMP(begin_cmd, cmds[idx]) == 0) { - break; - } - } - *end_cmd = save; - return idx; -} - -/* - * Find a sign by name. Also returns pointer to the previous sign. - */ - static sign_T * -sign_find(char_u *name, sign_T **sp_prev) -{ - sign_T *sp; - - if (sp_prev != NULL) - *sp_prev = NULL; - for (sp = first_sign; sp != NULL; sp = sp->sn_next) - { - if (STRCMP(sp->sn_name, name) == 0) - break; - if (sp_prev != NULL) - *sp_prev = sp; - } - - return sp; -} - -/* - * Define a new sign or update an existing sign - */ -int sign_define_by_name( - char_u *name, - char_u *icon, - char_u *linehl, - char_u *text, - char_u *texthl, - char_u *numhl -) -{ - sign_T *sp_prev; - sign_T *sp; - - sp = sign_find(name, &sp_prev); - 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 FAIL; - } - 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(name); - - // 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. - if (icon != NULL) - { - xfree(sp->sn_icon); - sp->sn_icon = vim_strsave(icon); - backslash_halve(sp->sn_icon); -# ifdef FEAT_SIGN_ICONS - if (gui.in_use) - { - out_flush(); - if (sp->sn_image != NULL) - gui_mch_destroy_sign(sp->sn_image); - sp->sn_image = gui_mch_register_sign(sp->sn_icon); - } -# endif - } - - if (text != NULL) - { - char_u *s; - char_u *endp; - int cells; - int len; - - endp = text + (int)STRLEN(text); - for (s = text; s + 1 < endp; ++s) { - if (*s == '\\') - { - // Remove a backslash, so that it is possible - // to use a space. - STRMOVE(s, s + 1); - --endp; - } - } - // Count cells and check for non-printable chars - cells = 0; - for (s = text; s < endp; s += (*mb_ptr2len)(s)) { - if (!vim_isprintc(utf_ptr2char(s))) { - break; - } - cells += utf_ptr2cells(s); - } - // Currently must be one or two display cells - if (s != endp || cells < 1 || cells > 2) { - EMSG2(_("E239: Invalid sign text: %s"), text); - return FAIL; - } - - xfree(sp->sn_text); - // Allocate one byte more if we need to pad up - // with a space. - len = (int)(endp - text + ((cells == 1) ? 1 : 0)); - sp->sn_text = vim_strnsave(text, len); - - if (cells == 1) - STRCPY(sp->sn_text + len - 1, " "); - } - - if (linehl != NULL) - sp->sn_line_hl = syn_check_group(linehl, (int)STRLEN(linehl)); - - if (texthl != NULL) - sp->sn_text_hl = syn_check_group(texthl, (int)STRLEN(texthl)); - - if (numhl != NULL) - sp->sn_num_hl = syn_check_group(numhl, (int)STRLEN(numhl)); - - return OK; -} - -/* - * Free the sign specified by 'name'. - */ - int -sign_undefine_by_name(char_u *name) -{ - sign_T *sp_prev; - sign_T *sp; - - sp = sign_find(name, &sp_prev); - if (sp == NULL) - { - EMSG2(_("E155: Unknown sign: %s"), name); - return FAIL; - } - sign_undefine(sp, sp_prev); - - return OK; -} - -/* - * List the signs matching 'name' - */ - static void -sign_list_by_name(char_u *name) -{ - sign_T *sp; - - sp = sign_find(name, NULL); - if (sp != NULL) - sign_list_defined(sp); - else - EMSG2(_("E155: Unknown sign: %s"), name); -} - -/* - * Place a sign at the specifed file location or update a sign. - */ -int sign_place( - int *sign_id, - char_u *sign_group, - char_u *sign_name, - buf_T *buf, - linenr_T lnum, - int prio -) -{ - sign_T *sp; - - // Check for reserved character '*' in group name - if (sign_group != NULL && (*sign_group == '*' || *sign_group == '\0')) { - return FAIL; - } - - 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 FAIL; - } - if (*sign_id == 0) - { - *sign_id = sign_group_get_next_signid(buf, sign_group); - } - - if (lnum > 0) { - // ":sign place {id} line={lnum} name={name} file={fname}": - // place a sign - buf_addsign(buf, *sign_id, sign_group, prio, lnum, sp->sn_typenr); - } else { - // ":sign place {id} file={fname}": change sign type - lnum = buf_change_sign_type(buf, *sign_id, sign_group, sp->sn_typenr); - } - if (lnum > 0) { - redraw_buf_line_later(buf, lnum); - } else { - EMSG2(_("E885: Not possible to change sign %s"), sign_name); - return FAIL; - } - - return OK; -} - -/* - * Unplace the specified sign - */ - int -sign_unplace(int sign_id, char_u *sign_group, buf_T *buf, linenr_T atlnum) -{ - if (buf->b_signlist == NULL) { // No signs in the buffer - return OK; - } - if (sign_id == 0) - { - // Delete all the signs in the specified buffer - redraw_buf_later(buf, NOT_VALID); - buf_delete_signs(buf, sign_group); - } else { - linenr_T lnum; - - // Delete only the specified signs - lnum = buf_delsign(buf, atlnum, sign_id, sign_group); - if (lnum == 0) { - return FAIL; - update_debug_sign(buf, lnum); - } - redraw_buf_line_later(buf, lnum); - } - - return OK; -} - -/* - * Unplace the sign at the current cursor line. - */ -static void sign_unplace_at_cursor(char_u *groupname) -{ - int id = -1; - - id = buf_findsign_id(curwin->w_buffer, curwin->w_cursor.lnum, groupname); - if (id > 0) { - sign_unplace(id, groupname, curwin->w_buffer, curwin->w_cursor.lnum); - } else { - EMSG(_("E159: Missing sign number")); - } -} - -/* - * sign define command - * ":sign define {name} ..." - */ -static void sign_define_cmd(char_u *sign_name, char_u *cmdline) -{ - char_u *arg; - char_u *p = cmdline; - char_u *icon = NULL; - char_u *text = NULL; - char_u *linehl = NULL; - char_u *texthl = NULL; - char_u *numhl = NULL; - int failed = FALSE; - - // 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; - icon = vim_strnsave(arg, (int)(p - arg)); - } else if (STRNCMP(arg, "text=", 5) == 0) { - arg += 5; - text = vim_strnsave(arg, (int)(p - arg)); - } else if (STRNCMP(arg, "linehl=", 7) == 0) { - arg += 7; - linehl = vim_strnsave(arg, (int)(p - arg)); - } else if (STRNCMP(arg, "texthl=", 7) == 0) { - arg += 7; - texthl = vim_strnsave(arg, (int)(p - arg)); - } else if (STRNCMP(arg, "numhl=", 6) == 0) { - arg += 6; - numhl = vim_strnsave(arg, (int)(p - arg)); - } else { - EMSG2(_(e_invarg2), arg); - failed = TRUE; - break; - } - } - - if (!failed) { - sign_define_by_name(sign_name, icon, linehl, text, texthl, numhl); - } - - xfree(icon); - xfree(text); - xfree(linehl); - xfree(texthl); - xfree(numhl); -} - -/* - * :sign place command - */ -static void sign_place_cmd( - buf_T *buf, - linenr_T lnum, - char_u *sign_name, - int id, - char_u *group, - int prio - ) -{ - if (id <= 0) - { - // List signs placed in a file/buffer - // :sign place file={fname} - // :sign place group={group} file={fname} - // :sign place group=* file={fname} - // :sign place buffer={nr} - // :sign place group={group} buffer={nr} - // :sign place group=* buffer={nr} - // :sign place - // :sign place group={group} - // :sign place group=* - if (lnum >= 0 || sign_name != NULL || - (group != NULL && *group == '\0')) { - EMSG(_(e_invarg)); - } else { - sign_list_placed(buf, group); - } - } else { - // Place a new sign - if (sign_name == NULL || buf == NULL || - (group != NULL && *group == '\0')) { - EMSG(_(e_invarg)); - return; - } - - sign_place(&id, group, sign_name, buf, lnum, prio); - } -} - -/* - * :sign unplace command - */ -static void sign_unplace_cmd( - buf_T *buf, - linenr_T lnum, - char_u *sign_name, - int id, - char_u *group -) -{ - if (lnum >= 0 || sign_name != NULL || (group != NULL && *group == '\0')) { - EMSG(_(e_invarg)); - return; - } - - if (id == -2) - { - if (buf != NULL) { - // :sign unplace * file={fname} - // :sign unplace * group={group} file={fname} - // :sign unplace * group=* file={fname} - // :sign unplace * buffer={nr} - // :sign unplace * group={group} buffer={nr} - // :sign unplace * group=* buffer={nr} - sign_unplace(0, group, buf, 0); - } else { - // :sign unplace * - // :sign unplace * group={group} - // :sign unplace * group=* - FOR_ALL_BUFFERS(buf) { - if (buf->b_signlist != NULL) { - buf_delete_signs(buf, group); - } - } - } - } else { - if (buf != NULL) { - // :sign unplace {id} file={fname} - // :sign unplace {id} group={group} file={fname} - // :sign unplace {id} group=* file={fname} - // :sign unplace {id} buffer={nr} - // :sign unplace {id} group={group} buffer={nr} - // :sign unplace {id} group=* buffer={nr} - sign_unplace(id, group, buf, 0); - } else { - if (id == -1) - { - // :sign unplace group={group} - // :sign unplace group=* - sign_unplace_at_cursor(group); - } else { - // :sign unplace {id} - // :sign unplace {id} group={group} - // :sign unplace {id} group=* - FOR_ALL_BUFFERS(buf) { - sign_unplace(id, group, buf, 0); - } - } - } - } -} - -/* - * Jump to a placed sign - * :sign jump {id} file={fname} - * :sign jump {id} buffer={nr} - * :sign jump {id} group={group} file={fname} - * :sign jump {id} group={group} buffer={nr} - */ -static void sign_jump_cmd( - buf_T *buf, - linenr_T lnum, - char_u *sign_name, - int id, - char_u *group - ) -{ - if (buf == NULL && sign_name == NULL && group == NULL && id == -1) { - EMSG(_(e_argreq)); - return; - } - - if (buf == NULL || (group != NULL && *group == '\0') || - lnum >= 0 || sign_name != NULL) { - // File or buffer is not specified or an empty group is used - // or a line number or a sign name is specified. - EMSG(_(e_invarg)); - return; - } - - if ((lnum = buf_findsign(buf, id, group)) <= 0) { - EMSGN(_("E157: Invalid sign ID: %ld"), id); - return; - } - - // 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(); -} - -/* - * Parse the command line arguments for the ":sign place", ":sign unplace" and - * ":sign jump" commands. - * The supported arguments are: line={lnum} name={name} group={group} - * priority={prio} and file={fname} or buffer={nr}. - */ -static int parse_sign_cmd_args( - int cmd, - char_u *arg, - char_u **sign_name, - int *signid, - char_u **group, - int *prio, - buf_T **buf, - linenr_T *lnum -) -{ - char_u *arg1; - char_u *name; - char_u *filename = NULL; - - // first arg could be placed sign id - arg1 = arg; - if (ascii_isdigit(*arg)) { - *signid = getdigits_int(&arg); - if (!ascii_iswhite(*arg) && *arg != NUL) { - *signid = -1; - arg = arg1; - } else { - arg = skipwhite(arg); - } - } - - while (*arg != NUL) { - if (STRNCMP(arg, "line=", 5) == 0) { - arg += 5; - *lnum = atoi((char *)arg); - arg = skiptowhite(arg); - } else if (STRNCMP(arg, "*", 1) == 0 && cmd == SIGNCMD_UNPLACE) { - if (*signid != -1) { - EMSG(_(e_invarg)); - return FAIL; - } - *signid = -2; - arg = skiptowhite(arg + 1); - } else if (STRNCMP(arg, "name=", 5) == 0) { - arg += 5; - name = arg; - arg = skiptowhite(arg); - if (*arg != NUL) { - *arg++ = NUL; - } - while (name[0] == '0' && name[1] != NUL) { - ++name; - } - *sign_name = name; - } else if (STRNCMP(arg, "group=", 6) == 0) { - arg += 6; - *group = arg; - arg = skiptowhite(arg); - if (*arg != NUL) { - *arg++ = NUL; - } - } else if (STRNCMP(arg, "priority=", 9) == 0) { - arg += 9; - *prio = atoi((char *)arg); - arg = skiptowhite(arg); - } else if (STRNCMP(arg, "file=", 5) == 0) { - arg += 5; - filename = arg; - *buf = buflist_findname_exp(arg); - break; - } else if (STRNCMP(arg, "buffer=", 7) == 0) { - arg += 7; - filename = arg; - *buf = buflist_findnr(getdigits_int(&arg)); - if (*skipwhite(arg) != NUL) { - EMSG(_(e_trailing)); - } - break; - } else { - EMSG(_(e_invarg)); - return FAIL; - } - arg = skipwhite(arg); - } - - if (filename != NULL && *buf == NULL) { - EMSG2(_("E158: Invalid buffer name: %s"), filename); - return FAIL; - } - - return OK; -} - -/* - * ":sign" command - */ -void ex_sign(exarg_T *eap) -{ - char_u *arg = eap->arg; - char_u *p; - int idx; - sign_T *sp; - - // 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 { - char_u *name; - - // 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++; - } - name = vim_strsave(arg); - - if (idx == SIGNCMD_DEFINE) { - sign_define_cmd(name, p); - } else if (idx == SIGNCMD_LIST) { - // ":sign list {name}" - sign_list_by_name(name); - } else { - // ":sign undefine {name}" - sign_undefine_by_name(name); - } - - xfree(name); - return; - } - } else { - int id = -1; - linenr_T lnum = -1; - char_u *sign_name = NULL; - char_u *group = NULL; - int prio = SIGN_DEF_PRIO; - buf_T *buf = NULL; - - // Parse command line arguments - if (parse_sign_cmd_args(idx, arg, &sign_name, &id, &group, &prio, - &buf, &lnum) == FAIL) - return; - - if (idx == SIGNCMD_PLACE) { - sign_place_cmd(buf, lnum, sign_name, id, group, prio); - } else if (idx == SIGNCMD_UNPLACE) { - sign_unplace_cmd(buf, lnum, sign_name, id, group); - } else if (idx == SIGNCMD_JUMP) { - sign_jump_cmd(buf, lnum, sign_name, id, group); - } - } -} - -/* - * Return information about a specified sign - */ -static void sign_getinfo(sign_T *sp, dict_T *retdict) -{ - char_u *p; - - tv_dict_add_str(retdict, S_LEN("name"), (char_u *)sp->sn_name); - if (sp->sn_icon != NULL) { - tv_dict_add_str(retdict, S_LEN("icon"), (char_u *)sp->sn_icon); - } - if (sp->sn_text != NULL) { - tv_dict_add_str(retdict, S_LEN("text"), (char_u *)sp->sn_text); - } - if (sp->sn_line_hl > 0) { - p = get_highlight_name_ext(NULL, sp->sn_line_hl - 1, FALSE); - if (p == NULL) { - p = (char_u *)"NONE"; - } - tv_dict_add_str(retdict, S_LEN("linehl"), (char_u *)p); - } - if (sp->sn_text_hl > 0) { - p = get_highlight_name_ext(NULL, sp->sn_text_hl - 1, FALSE); - if (p == NULL) { - p = (char_u *)"NONE"; - } - tv_dict_add_str(retdict, S_LEN("texthl"), (char_u *)p); - } - if (sp->sn_num_hl > 0) { - p = get_highlight_name_ext(NULL, sp->sn_num_hl - 1, FALSE); - if (p == NULL) { - p = (char_u *)"NONE"; - } - tv_dict_add_str(retdict, S_LEN("numhl"), (char_u *)p); - } -} - -/* - * If 'name' is NULL, return a list of all the defined signs. - * Otherwise, return information about the specified sign. - */ -void sign_getlist(char_u *name, list_T *retlist) -{ - sign_T *sp = first_sign; - dict_T *dict; - - if (name != NULL) { - sp = sign_find(name, NULL); - if (sp == NULL) { - return; - } - } - - for (; sp != NULL && !got_int; sp = sp->sn_next) { - if ((dict = tv_dict_alloc()) == NULL) { - return; - } - tv_list_append_dict(retlist, dict); - sign_getinfo(sp, dict); - - if (name != NULL) { // handle only the specified sign - break; - } - } -} - -/* - * Return information about all the signs placed in a buffer - */ -static void sign_get_placed_in_buf( - buf_T *buf, - linenr_T lnum, - int sign_id, - char_u *sign_group, - list_T *retlist) -{ - dict_T *d; - list_T *l; - signlist_T *sign; - dict_T *sdict; - - if ((d = tv_dict_alloc()) == NULL) { - return; - } - tv_list_append_dict(retlist, d); - - tv_dict_add_nr(d, S_LEN("bufnr"), (long)buf->b_fnum); - - if ((l = tv_list_alloc(kListLenMayKnow)) == NULL) { - return; - } - tv_dict_add_list(d, S_LEN("signs"), l); - - FOR_ALL_SIGNS_IN_BUF(buf, sign) { - if (!sign_in_group(sign, sign_group)) { - continue; - } - if ((lnum == 0 && sign_id == 0) || - (sign_id == 0 && lnum == sign->lnum) || - (lnum == 0 && sign_id == sign->id) || - (lnum == sign->lnum && sign_id == sign->id)) { - if ((sdict = sign_get_info(sign)) != NULL) { - tv_list_append_dict(l, sdict); - } - } - } -} - -/* - * Get a list of signs placed in buffer 'buf'. If 'num' is non-zero, return the - * sign placed at the line number. If 'lnum' is zero, return all the signs - * placed in 'buf'. If 'buf' is NULL, return signs placed in all the buffers. - */ -void sign_get_placed( - buf_T *buf, - linenr_T lnum, - int sign_id, - char_u *sign_group, - list_T *retlist) -{ - if (buf != NULL) { - sign_get_placed_in_buf(buf, lnum, sign_id, sign_group, retlist); - } else { - FOR_ALL_BUFFERS(buf) { - if (buf->b_signlist != NULL) { - sign_get_placed_in_buf(buf, 0, sign_id, sign_group, retlist); - } - } - } -} - -/* - * List one sign. - */ -static void sign_list_defined(sign_T *sp) -{ - smsg("sign %s", sp->sn_name); - if (sp->sn_icon != NULL) { - msg_puts(" icon="); - msg_outtrans(sp->sn_icon); - msg_puts(_(" (not supported)")); - } - if (sp->sn_text != NULL) { - msg_puts(" text="); - msg_outtrans(sp->sn_text); - } - if (sp->sn_line_hl > 0) { - msg_puts(" linehl="); - const char *const p = get_highlight_name_ext(NULL, - sp->sn_line_hl - 1, false); - if (p == NULL) { - msg_puts("NONE"); - } else { - msg_puts(p); - } - } - if (sp->sn_text_hl > 0) { - msg_puts(" texthl="); - const char *const p = get_highlight_name_ext(NULL, - sp->sn_text_hl - 1, false); - if (p == NULL) { - msg_puts("NONE"); - } else { - msg_puts(p); - } - } - if (sp->sn_num_hl > 0) { - msg_puts(" numhl="); - const char *const p = get_highlight_name_ext(NULL, - sp->sn_num_hl - 1, false); - if (p == NULL) { - msg_puts("NONE"); - } else { - msg_puts(p); - } - } -} - -/* - * Undefine a sign and free its memory. - */ -static void sign_undefine(sign_T *sp, sign_T *sp_prev) -{ - xfree(sp->sn_name); - xfree(sp->sn_icon); - xfree(sp->sn_text); - if (sp_prev == NULL) - first_sign = sp->sn_next; - else - sp_prev->sn_next = sp->sn_next; - xfree(sp); -} - -/// Gets highlighting attribute for sign "typenr" corresponding to "type". -int sign_get_attr(int typenr, SignType type) -{ - sign_T *sp; - int sign_hl = 0; - - for (sp = first_sign; sp != NULL; sp = sp->sn_next) { - if (sp->sn_typenr == typenr) { - switch (type) { - case SIGN_TEXT: - sign_hl = sp->sn_text_hl; - break; - case SIGN_LINEHL: - sign_hl = sp->sn_line_hl; - break; - case SIGN_NUMHL: - sign_hl = sp->sn_num_hl; - break; - default: - abort(); - } - if (sign_hl > 0) { - return syn_id2attr(sign_hl); - } - break; - } - } - return 0; -} - -/* - * Get text mark for sign "typenr". - * Returns NULL if there isn't one. - */ -char_u * sign_get_text(int typenr) -{ - sign_T *sp; - - for (sp = first_sign; sp != NULL; sp = sp->sn_next) - if (sp->sn_typenr == typenr) - return sp->sn_text; - return NULL; -} - - -/* - * Get the name of a sign by its typenr. - */ -char_u * sign_typenr2name(int typenr) -{ - sign_T *sp; - - for (sp = first_sign; sp != NULL; sp = sp->sn_next) - if (sp->sn_typenr == typenr) - return sp->sn_name; - return (char_u *)_("[Deleted]"); -} - -/* - * Undefine/free all signs. - */ -void free_signs(void) -{ - while (first_sign != NULL) - sign_undefine(first_sign, NULL); -} - -static enum -{ - EXP_SUBCMD, /* expand :sign sub-commands */ - EXP_DEFINE, /* expand :sign define {name} args */ - EXP_PLACE, /* expand :sign place {id} args */ - EXP_UNPLACE, /* expand :sign unplace" */ - EXP_SIGN_NAMES /* expand with name of placed signs */ -} expand_what; - -/// Function given to ExpandGeneric() to obtain the sign command -/// expansion. -char_u * get_sign_name(expand_T *xp, int idx) -{ - switch (expand_what) - { - case EXP_SUBCMD: - return (char_u *)cmds[idx]; - case EXP_DEFINE: { - char *define_arg[] = { "icon=", "linehl=", "text=", "texthl=", "numhl=", - NULL }; - return (char_u *)define_arg[idx]; - } - case EXP_PLACE: { - char *place_arg[] = { "line=", "name=", "group=", "priority=", "file=", - "buffer=", NULL }; - return (char_u *)place_arg[idx]; - } - case EXP_UNPLACE: { - char *unplace_arg[] = { "group=", "file=", "buffer=", NULL }; - return (char_u *)unplace_arg[idx]; - } - case EXP_SIGN_NAMES: { - // Complete with name of signs already defined - int current_idx = 0; - for (sign_T *sp = first_sign; sp != NULL; sp = sp->sn_next) { - if (current_idx++ == idx) { - return sp->sn_name; - } - } - } - return NULL; - default: - return NULL; - } -} - -/* - * Handle command line completion for :sign command. - */ -void set_context_in_sign_cmd(expand_T *xp, char_u *arg) -{ - char_u *p; - char_u *end_subcmd; - char_u *last; - int cmd_idx; - char_u *begin_subcmd_args; - - /* Default: expand subcommands. */ - xp->xp_context = EXPAND_SIGN; - expand_what = EXP_SUBCMD; - xp->xp_pattern = arg; - - end_subcmd = skiptowhite(arg); - if (*end_subcmd == NUL) - /* expand subcmd name - * :sign {subcmd}<CTRL-D>*/ - return; - - cmd_idx = sign_cmd_idx(arg, end_subcmd); - - // :sign {subcmd} {subcmd_args} - // | - // begin_subcmd_args - begin_subcmd_args = skipwhite(end_subcmd); - p = skiptowhite(begin_subcmd_args); - if (*p == NUL) - { - /* - * Expand first argument of subcmd when possible. - * For ":jump {id}" and ":unplace {id}", we could - * possibly expand the ids of all signs already placed. - */ - xp->xp_pattern = begin_subcmd_args; - switch (cmd_idx) - { - case SIGNCMD_LIST: - case SIGNCMD_UNDEFINE: - /* :sign list <CTRL-D> - * :sign undefine <CTRL-D> */ - expand_what = EXP_SIGN_NAMES; - break; - default: - xp->xp_context = EXPAND_NOTHING; - } - return; - } - - // Expand last argument of subcmd. - // - // :sign define {name} {args}... - // | - // p - - // Loop until reaching last argument. - do - { - p = skipwhite(p); - last = p; - p = skiptowhite(p); - } while (*p != NUL); - - p = vim_strchr(last, '='); - - // :sign define {name} {args}... {last}= - // | | - // last p - if (p == NULL) { - // Expand last argument name (before equal sign). - xp->xp_pattern = last; - switch (cmd_idx) - { - case SIGNCMD_DEFINE: - expand_what = EXP_DEFINE; - break; - case SIGNCMD_PLACE: - expand_what = EXP_PLACE; - break; - case SIGNCMD_JUMP: - case SIGNCMD_UNPLACE: - expand_what = EXP_UNPLACE; - break; - default: - xp->xp_context = EXPAND_NOTHING; - } - } - else - { - /* Expand last argument value (after equal sign). */ - xp->xp_pattern = p + 1; - switch (cmd_idx) - { - case SIGNCMD_DEFINE: - if (STRNCMP(last, "texthl", p - last) == 0 - || STRNCMP(last, "linehl", p - last) == 0 - || STRNCMP(last, "numhl", p - last) == 0) { - xp->xp_context = EXPAND_HIGHLIGHT; - } else if (STRNCMP(last, "icon", p - last) == 0) { - xp->xp_context = EXPAND_FILES; - } else { - xp->xp_context = EXPAND_NOTHING; - } - break; - case SIGNCMD_PLACE: - if (STRNCMP(last, "name", p - last) == 0) - expand_what = EXP_SIGN_NAMES; - else - xp->xp_context = EXPAND_NOTHING; - break; - default: - xp->xp_context = EXPAND_NOTHING; - } - } -} - /// Shows the effects of the :substitute command being typed ('inccommand'). /// If inccommand=split, shows a preview window and later restores the layout. static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, |