changeset 15418:51b3c36b0523 v8.1.0717

patch 8.1.0717: there is no function for the ":sign jump" command commit https://github.com/vim/vim/commit/6b7b7190aa9e5c4f51bceaebf9275aa5097cfea1 Author: Bram Moolenaar <Bram@vim.org> Date: Fri Jan 11 13:42:41 2019 +0100 patch 8.1.0717: there is no function for the ":sign jump" command Problem: There is no function for the ":sign jump" command. Solution: Add the sign_jump() function. (Yegappan Lakshmanan, closes https://github.com/vim/vim/issues/3780)
author Bram Moolenaar <Bram@vim.org>
date Fri, 11 Jan 2019 13:45:06 +0100
parents 50a5ad000845
children 74088e9d6b52
files runtime/doc/eval.txt runtime/doc/sign.txt runtime/doc/usr_41.txt src/evalfunc.c src/proto/sign.pro src/sign.c src/testdir/test_signs.vim src/version.c
diffstat 8 files changed, 237 insertions(+), 103 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -2412,6 +2412,8 @@ sign_define({name} [, {dict}])	Number	de
 sign_getdefined([{name}])	List	get a list of defined signs
 sign_getplaced([{expr} [, {dict}]])
 				List	get a list of placed signs
+sign_jump({id}, {group}, {expr})
+				Number	jump to a sign
 sign_place({id}, {group}, {name}, {expr} [, {dict}])
 				Number	place a sign
 sign_undefine([{name}])		Number	undefine a sign
@@ -7998,6 +8000,21 @@ sign_getplaced([{expr} [, {dict}]])			*s
 			" Get a List of all the placed signs
 			echo sign_getplaced()
 <
+							*sign_jump()*
+sign_jump({id}, {group}, {expr})
+		Open the buffer {expr} or jump to the window that contains
+		{expr} and position the cursor at sign {id} in group {group}.
+		This is similar to the |:sign-jump| command.
+
+		For the use of {expr}, see |bufname()|.
+
+		Returns the line number of the sign. Returns -1 if the
+		arguments are invalid.
+
+		Example: >
+			" Jump to sign 10 in the current buffer
+			call sign_jump(10, '', '')
+<
 							*sign_place()*
 sign_place({id}, {group}, {name}, {expr} [, {dict}])
 		Place the sign defined as {name} at line {lnum} in file {expr}
--- a/runtime/doc/sign.txt
+++ b/runtime/doc/sign.txt
@@ -263,13 +263,13 @@ See |sign_unplace()| for the equivalent 
 		all the files it appears in.
 
 :sign unplace *
-		Remove placed signs in the global group from all the files.
+		Remove all placed signs in the global group from all the files.
 
 :sign unplace * group={group}
-		Remove placed signs in group {group} from all the files.
+		Remove all placed signs in group {group} from all the files.
 
 :sign unplace * group=*
-		Remove placed signs in all the groups from all the files.
+		Remove all placed signs in all the groups from all the files.
 
 :sign unplace
 		Remove a placed sign at the cursor position. If multiple signs
@@ -317,6 +317,8 @@ See |sign_getplaced()| for the equivalen
 
 JUMPING TO A SIGN					*:sign-jump* *E157*
 
+See |sign_jump()| for the equivalent Vim script function.
+
 :sign jump {id} file={fname}
 		Open the file {fname} or jump to the window that contains
 		{fname} and position the cursor at sign {id}.
--- a/runtime/doc/usr_41.txt
+++ b/runtime/doc/usr_41.txt
@@ -987,6 +987,7 @@ Signs:						*sign-functions*
 	sign_define()		define or update a sign
 	sign_getdefined()	get a list of defined signs
 	sign_getplaced()	get a list of placed signs
+	sign_jump()		jump to a sign
 	sign_place()		place a sign
 	sign_undefine()		undefine a sign
 	sign_unplace()		unplace a sign
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -371,6 +371,7 @@ static void f_shiftwidth(typval_T *argva
 static void f_sign_define(typval_T *argvars, typval_T *rettv);
 static void f_sign_getdefined(typval_T *argvars, typval_T *rettv);
 static void f_sign_getplaced(typval_T *argvars, typval_T *rettv);
+static void f_sign_jump(typval_T *argvars, typval_T *rettv);
 static void f_sign_place(typval_T *argvars, typval_T *rettv);
 static void f_sign_undefine(typval_T *argvars, typval_T *rettv);
 static void f_sign_unplace(typval_T *argvars, typval_T *rettv);
@@ -858,6 +859,7 @@ static struct fst
     {"sign_define",	1, 2, f_sign_define},
     {"sign_getdefined",	0, 1, f_sign_getdefined},
     {"sign_getplaced",	0, 2, f_sign_getplaced},
+    {"sign_jump",	3, 3, f_sign_jump},
     {"sign_place",	4, 5, f_sign_place},
     {"sign_undefine",	0, 1, f_sign_undefine},
     {"sign_unplace",	1, 2, f_sign_unplace},
@@ -1918,6 +1920,23 @@ tv_get_buf(typval_T *tv, int curtab_only
 }
 
 /*
+ * Get the buffer from "arg" and give an error and return NULL if it is not
+ * valid.
+ */
+    static buf_T *
+get_buf_arg(typval_T *arg)
+{
+    buf_T *buf;
+
+    ++emsg_off;
+    buf = tv_get_buf(arg, FALSE);
+    --emsg_off;
+    if (buf == NULL)
+	EMSG2(_("E158: Invalid buffer name: %s"), tv_get_string(arg));
+    return buf;
+}
+
+/*
  * "bufname(expr)" function
  */
     static void
@@ -11366,14 +11385,10 @@ f_sign_getplaced(typval_T *argvars, typv
 
     if (argvars[0].v_type != VAR_UNKNOWN)
     {
-	// get signs placed in this buffer
-	buf = tv_get_buf(&argvars[0], FALSE);
+	// get signs placed in the specified buffer
+	buf = get_buf_arg(&argvars[0]);
 	if (buf == NULL)
-	{
-	    EMSG2(_("E158: Invalid buffer name: %s"),
-						tv_get_string(&argvars[0]));
 	    return;
-	}
 
 	if (argvars[1].v_type != VAR_UNKNOWN)
 	{
@@ -11413,6 +11428,53 @@ f_sign_getplaced(typval_T *argvars, typv
 }
 
 /*
+ * "sign_jump()" function
+ */
+    static void
+f_sign_jump(typval_T *argvars, typval_T *rettv)
+{
+    int		sign_id;
+    char_u	*sign_group = NULL;
+    buf_T	*buf;
+    int		notanum = FALSE;
+
+    rettv->vval.v_number = -1;
+
+    // Sign identifer
+    sign_id = (int)tv_get_number_chk(&argvars[0], &notanum);
+    if (notanum)
+	return;
+    if (sign_id <= 0)
+    {
+	EMSG(_(e_invarg));
+	return;
+    }
+
+    // Sign group
+    sign_group = tv_get_string_chk(&argvars[1]);
+    if (sign_group == NULL)
+	return;
+    if (sign_group[0] == '\0')
+	sign_group = NULL;			// global sign group
+    else
+    {
+	sign_group = vim_strsave(sign_group);
+	if (sign_group == NULL)
+	    return;
+    }
+
+    // Buffer to place the sign
+    buf = get_buf_arg(&argvars[2]);
+    if (buf == NULL)
+	goto cleanup;
+
+    rettv->vval.v_number = sign_jump(sign_id, sign_group, buf);
+
+cleanup:
+    vim_free(sign_group);
+}
+
+/*
  * "sign_place()" function
  */
     static void
@@ -11459,12 +11521,9 @@ f_sign_place(typval_T *argvars, typval_T
 	goto cleanup;
 
     // Buffer to place the sign
-    buf = tv_get_buf(&argvars[3], FALSE);
+    buf = get_buf_arg(&argvars[3]);
     if (buf == NULL)
-    {
-	EMSG2(_("E158: Invalid buffer name: %s"), tv_get_string(&argvars[3]));
 	goto cleanup;
-    }
 
     if (argvars[4].v_type != VAR_UNKNOWN)
     {
@@ -11568,13 +11627,9 @@ f_sign_unplace(typval_T *argvars, typval
 
 	if ((di = dict_find(dict, (char_u *)"buffer", -1)) != NULL)
 	{
-	    buf = tv_get_buf(&di->di_tv, FALSE);
+	    buf = get_buf_arg(&di->di_tv);
 	    if (buf == NULL)
-	    {
-		EMSG2(_("E158: Invalid buffer name: %s"),
-						tv_get_string(&di->di_tv));
 		goto cleanup;
-	    }
 	}
 	if (dict_find(dict, (char_u *)"id", -1) != NULL)
 	    sign_id = dict_get_number(dict, (char_u *)"id");
--- a/src/proto/sign.pro
+++ b/src/proto/sign.pro
@@ -11,6 +11,7 @@ void sign_mark_adjust(linenr_T line1, li
 int sign_define_by_name(char_u *name, char_u *icon, char_u *linehl, char_u *text, char_u *texthl);
 int sign_undefine_by_name(char_u *name);
 int sign_place(int *sign_id, char_u *sign_group, char_u *sign_name, buf_T *buf, linenr_T lnum, int prio);
+linenr_T sign_jump(int sign_id, char_u *sign_group, buf_T *buf);
 int sign_unplace(int sign_id, char_u *sign_group, buf_T *buf, linenr_T atlnum);
 void ex_sign(exarg_T *eap);
 void sign_getlist(char_u *name, list_T *retlist);
--- a/src/sign.c
+++ b/src/sign.c
@@ -22,16 +22,16 @@ typedef struct sign sign_T;
 
 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 */
+    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
 # ifdef FEAT_SIGN_ICONS
-    void	*sn_image;	/* icon image */
+    void	*sn_image;	// icon image
 # endif
-    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 */
+    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
 };
 
 static sign_T	*first_sign = NULL;
@@ -381,9 +381,9 @@ buf_change_sign_type(
 buf_getsigntype(
     buf_T	*buf,
     linenr_T	lnum,
-    int		type)	/* SIGN_ICON, SIGN_TEXT, SIGN_ANY, SIGN_LINEHL */
+    int		type)	// SIGN_ICON, SIGN_TEXT, SIGN_ANY, SIGN_LINEHL
 {
-    signlist_T	*sign;		/* a sign in a b_signlist */
+    signlist_T	*sign;		// a sign in a b_signlist
 
     FOR_ALL_SIGNS_IN_BUF(buf, sign)
 	if (sign->lnum == lnum
@@ -526,11 +526,11 @@ buf_findsign_id(
  */
     int
 buf_findsigntype_id(
-    buf_T	*buf,		/* buffer whose sign we are searching for */
-    linenr_T	lnum,		/* line number of sign */
-    int		typenr)		/* sign type number */
+    buf_T	*buf,		// buffer whose sign we are searching for
+    linenr_T	lnum,		// line number of sign
+    int		typenr)		// sign type number
 {
-    signlist_T	*sign;		/* a sign in the signlist */
+    signlist_T	*sign;		// a sign in the signlist
 
     FOR_ALL_SIGNS_IN_BUF(buf, sign)
 	if (sign->lnum == lnum && sign->typenr == typenr)
@@ -656,7 +656,7 @@ sign_mark_adjust(
     long	amount,
     long	amount_after)
 {
-    signlist_T	*sign;		/* a sign in a b_signlist */
+    signlist_T	*sign;		// a sign in a b_signlist
 
     FOR_ALL_SIGNS_IN_BUF(curbuf, sign)
     {
@@ -678,8 +678,8 @@ sign_mark_adjust(
  */
     static int
 sign_cmd_idx(
-    char_u	*begin_cmd,	/* begin of sign subcmd */
-    char_u	*end_cmd)	/* just after sign subcmd */
+    char_u	*begin_cmd,	// begin of sign subcmd
+    char_u	*end_cmd)	// just after sign subcmd
 {
     int		idx;
     char	save = *end_cmd;
@@ -984,8 +984,51 @@ sign_unplace_at_cursor(char_u *groupname
 }
 
 /*
- * sign define command
- *   ":sign define {name} ..."
+ * Jump to a sign.
+ */
+    linenr_T
+sign_jump(int sign_id, char_u *sign_group, buf_T *buf)
+{
+    linenr_T	lnum;
+
+    if ((lnum = buf_findsign(buf, sign_id, sign_group)) <= 0)
+    {
+	EMSGN(_("E157: Invalid sign ID: %ld"), sign_id);
+	return -1;
+    }
+
+    // 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_u	*cmd;
+
+	if (buf->b_fname == NULL)
+	{
+	    EMSG(_("E934: Cannot jump to a buffer that does not have a name"));
+	    return -1;
+	}
+	cmd = alloc((unsigned)STRLEN(buf->b_fname) + 25);
+	if (cmd == NULL)
+	    return -1;
+	sprintf((char *)cmd, "e +%ld %s", (long)lnum, buf->b_fname);
+	do_cmdline_cmd(cmd);
+	vim_free(cmd);
+    }
+# ifdef FEAT_FOLDING
+    foldOpenCursor();
+# endif
+
+    return lnum;
+}
+
+/*
+ * ":sign define {name} ..." command
  */
     static void
 sign_define_cmd(char_u *sign_name, char_u *cmdline)
@@ -1043,7 +1086,7 @@ sign_define_cmd(char_u *sign_name, char_
 }
 
 /*
- * :sign place command
+ * ":sign place" command
  */
     static void
 sign_place_cmd(
@@ -1087,7 +1130,7 @@ sign_place_cmd(
 }
 
 /*
- * :sign unplace command
+ * ":sign unplace" command
  */
     static void
 sign_unplace_cmd(
@@ -1152,7 +1195,7 @@ sign_unplace_cmd(
 }
 
 /*
- * Jump to a placed sign
+ * Jump to a placed sign commands:
  *   :sign jump {id} file={fname}
  *   :sign jump {id} buffer={nr}
  *   :sign jump {id} group={group} file={fname}
@@ -1180,39 +1223,7 @@ sign_jump_cmd(
 	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
-	char_u	*cmd;
-
-	if (buf->b_fname == NULL)
-	{
-	    EMSG(_("E934: Cannot jump to a buffer that does not have a name"));
-	    return;
-	}
-	cmd = alloc((unsigned)STRLEN(buf->b_fname) + 25);
-	if (cmd == NULL)
-	    return;
-	sprintf((char *)cmd, "e +%ld %s", (long)lnum, buf->b_fname);
-	do_cmdline_cmd(cmd);
-	vim_free(cmd);
-    }
-# ifdef FEAT_FOLDING
-    foldOpenCursor();
-# endif
+    (void)sign_jump(id, group, buf);
 }
 
 /*
@@ -1685,7 +1696,7 @@ sign_get_text(int typenr)
 # if defined(FEAT_SIGN_ICONS) || defined(PROTO)
     void *
 sign_get_image(
-    int		typenr)		/* the attribute which may have a sign */
+    int		typenr)		// the attribute which may have a sign
 {
     sign_T	*sp;
 
@@ -1709,11 +1720,11 @@ free_signs(void)
 # if defined(FEAT_CMDL_COMPL) || defined(PROTO)
 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 */
+    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;
 
 /*
@@ -1753,7 +1764,7 @@ get_sign_name(expand_T *xp UNUSED, int i
 	    return (char_u *)unplace_arg[idx];
 	}
     case EXP_SIGN_NAMES:
-	/* Complete with name of signs already defined */
+	// Complete with name of signs already defined
 	current_idx = 0;
 	for (sp = first_sign; sp != NULL; sp = sp->sn_next)
 	    if (current_idx++ == idx)
@@ -1776,38 +1787,38 @@ set_context_in_sign_cmd(expand_T *xp, ch
     int		cmd_idx;
     char_u	*begin_subcmd_args;
 
-    /* Default: expand subcommands. */
+    // 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>*/
+	// expand subcmd name
+	// :sign {subcmd}<CTRL-D>
 	return;
 
     cmd_idx = sign_cmd_idx(arg, end_subcmd);
 
-    /* :sign {subcmd} {subcmd_args}
-     *		      |
-     *		      begin_subcmd_args */
+    // :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.
-	 */
+	//
+	// 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> */
+		// :sign list <CTRL-D>
+		// :sign undefine <CTRL-D>
 		expand_what = EXP_SIGN_NAMES;
 		break;
 	    default:
@@ -1816,13 +1827,13 @@ set_context_in_sign_cmd(expand_T *xp, ch
 	return;
     }
 
-    /* expand last argument of subcmd */
+    // expand last argument of subcmd
 
-    /* :sign define {name} {args}...
-     *		    |
-     *		    p */
+    // :sign define {name} {args}...
+    //		    |
+    //		    p
 
-    /* Loop until reaching last argument. */
+    // Loop until reaching last argument.
     do
     {
 	p = skipwhite(p);
@@ -1832,12 +1843,12 @@ set_context_in_sign_cmd(expand_T *xp, ch
 
     p = vim_strchr(last, '=');
 
-    /* :sign define {name} {args}... {last}=
-     *				     |	   |
-     *				  last	   p */
+    // :sign define {name} {args}... {last}=
+    //				     |	   |
+    //				  last	   p
     if (p == NULL)
     {
-	/* Expand last argument name (before equal sign). */
+	// Expand last argument name (before equal sign).
 	xp->xp_pattern = last;
 	switch (cmd_idx)
 	{
@@ -1857,7 +1868,7 @@ set_context_in_sign_cmd(expand_T *xp, ch
     }
     else
     {
-	/* Expand last argument value (after equal sign). */
+	// Expand last argument value (after equal sign).
 	xp->xp_pattern = p + 1;
 	switch (cmd_idx)
 	{
--- a/src/testdir/test_signs.vim
+++ b/src/testdir/test_signs.vim
@@ -1255,3 +1255,48 @@ func Test_sign_change_type()
   sign undefine sign2
   enew!
 endfunc
+
+" Test for the sign_jump() function
+func Test_sign_jump_func()
+  enew! | only!
+
+  sign define sign1 text=#> linehl=Comment
+
+  edit foo
+  set buftype=nofile
+  call setline(1, ['A', 'B', 'C', 'D', 'E'])
+  call sign_place(5, '', 'sign1', '', {'lnum' : 2})
+  call sign_place(5, 'g1', 'sign1', '', {'lnum' : 3})
+  call sign_place(6, '', 'sign1', '', {'lnum' : 4})
+  call sign_place(6, 'g1', 'sign1', '', {'lnum' : 5})
+  split bar
+  set buftype=nofile
+  call setline(1, ['P', 'Q', 'R', 'S', 'T'])
+  call sign_place(5, '', 'sign1', '', {'lnum' : 2})
+  call sign_place(5, 'g1', 'sign1', '', {'lnum' : 3})
+  call sign_place(6, '', 'sign1', '', {'lnum' : 4})
+  call sign_place(6, 'g1', 'sign1', '', {'lnum' : 5})
+
+  let r = sign_jump(5, '', 'foo')
+  call assert_equal(2, r)
+  call assert_equal(2, line('.'))
+  let r = sign_jump(6, 'g1', 'foo')
+  call assert_equal(5, r)
+  call assert_equal(5, line('.'))
+  let r = sign_jump(5, '', 'bar')
+  call assert_equal(2, r)
+  call assert_equal(2, line('.'))
+
+  " Error cases
+  call assert_fails("call sign_jump(99, '', 'bar')", 'E157:')
+  call assert_fails("call sign_jump(0, '', 'foo')", 'E474:')
+  call assert_fails("call sign_jump(5, 'g5', 'foo')", 'E157:')
+  call assert_fails('call sign_jump([], "", "foo")', 'E745:')
+  call assert_fails('call sign_jump(2, [], "foo")', 'E730:')
+  call assert_fails('call sign_jump(2, "", {})', 'E158:')
+  call assert_fails('call sign_jump(2, "", "baz")', 'E158:')
+
+  sign unplace * group=*
+  sign undefine sign1
+  enew! | only!
+endfunc
--- a/src/version.c
+++ b/src/version.c
@@ -800,6 +800,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    717,
+/**/
     716,
 /**/
     715,