Hi Bram!

On Do, 04 Aug 2011, Bram Moolenaar wrote:

> > What about  [h and ]h, which would move to the next/previous instance of 
> > the highlighting group specified in a new vim option; as a suggestion, 
> > jumphlgroup .  This would be instead of [t and ]t, and could be used 
> > instead of [e and]e, too, I suppose.
> 
> That sounds like a good idea.  The option can be set depending on the
> language, by a filetype plugin. It can be a list of highlight groups, so
> that you can tell where ]h and [h stop.  You could also make a mapping
> that sets the option and then does the ]h, to jump to specific
> highlights.

Here we go an updated patch.

The comments should explain how it works. I intentionally commented out 
some parts of it. You may enable, if you like it. (basically, how moving 
backwards works).

One thing, I still haven't looked at how to add moving to parts that are 
highlighted because of the match() functions. 

regards,
Christian
-- 
Demnächst sollen auch die ersten Landesmeisterschaften im
Beamtendreikampf ausgerichtet werden: Knicken, Lochen, Abheften.

-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
diff --git a/runtime/doc/motion.txt b/runtime/doc/motion.txt
--- a/runtime/doc/motion.txt
+++ b/runtime/doc/motion.txt
@@ -1289,6 +1289,16 @@
 ]*  or  ]/		go to [count] next end of a C comment "*/".
 			|exclusive| motion. {not in Vi}
 
+						        *]e*
+]h			go to [count] next item that is highlighted like
+			'jhl' specifies.
+			Needs |:syntax-on| |exclusive| motion.
+			{not in Vi}
+
+						        *[e*
+[h			go to [count] previous item that is highlighted like
+			'jhl' specifies. Needs |:syntax-on| |exclusive| motion.
+			{not in Vi}
 
 						*H*
 H			To line [count] from top (Home) of window (default:
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -4327,6 +4327,13 @@
 	Otherwise only one space is inserted.
 	NOTE: This option is set when 'compatible' is set.
 
+			*'jumphlgroup'* *'jhl'* *'nojumphlgroup'* *'nojhl'*
+'joinspaces' 'js'	string	(Vim default "Error", Vi default "")
+			local
+			{not in Vi}
+	Defines the highlighting group to which the |]h| and |[h] motion
+	moves. Only works, when syntax highlighting is enabled |syntax-on|
+
 							*'key'*
 'key'			string	(default "")
 			local to buffer
diff --git a/runtime/optwin.vim b/runtime/optwin.vim
--- a/runtime/optwin.vim
+++ b/runtime/optwin.vim
@@ -393,6 +393,9 @@
   call append("$", "synmaxcol\tmaximum column to look for syntax items")
   call append("$", "\t(local to buffer)")
   call <SID>OptionL("smc")
+  call append("$", "jumphlgroup\tHighlight group to which ]h jumps")
+  call append("$", "\t(local to buffer)")
+  call <SID>OptionL("jhl")
 endif
 call append("$", "highlight\twhich highlighting to use for various occasions")
 call <SID>OptionG("hl", &hl)
diff --git a/src/normal.c b/src/normal.c
--- a/src/normal.c
+++ b/src/normal.c
@@ -185,6 +185,7 @@
 #ifdef FEAT_AUTOCMD
 static void	nv_cursorhold __ARGS((cmdarg_T *cap));
 #endif
+int  syn_move_to __ARGS((int, int, int*));
 
 static char *e_noident = N_("E349: No identifier under cursor");
 
@@ -6684,6 +6685,26 @@
 	    clearopbeep(cap->oap);
     }
 #endif
+    /*
+     * "[e" and "]e": move to previous or next error highlight
+     * "[t" and "]t": move to previous or next TODO highlight
+     */
+    else if (cap->nchar == 'h')
+    {
+	if (syn_move_to(cap->cmdchar == ']' ? FORWARD : BACKWARD,
+			cap->count1, curbuf->b_p_jhlids) == FAIL)
+	    clearopbeep(cap->oap);
+	else
+	{
+#ifdef FEAT_FOLDING
+	    if ((fdo_flags & FDO_BLOCK) && KeyTyped && cap->oap->op_type == OP_NOP)
+		foldOpenCursor();
+#endif
+
+	    /* Some screen updating artifacts? */
+	    update_curbuf(VALID);
+	}
+    }
 
 #ifdef FEAT_DIFF
     /*
@@ -9457,3 +9478,91 @@
     cap->retval |= CA_COMMAND_BUSY;	/* don't call edit() now */
 }
 #endif
+
+/*
+ * Move to next syntax error.
+ * dir is forward or backward, attr is Highligh group to look for
+ */
+    int
+syn_move_to(dir, count, attr)
+    int		dir;		/* FORWARD or BACKWARD */
+    int		count;
+    int	        *attr;
+{
+    pos_T	pos;
+#ifdef FEAT_SYN_HL
+    int		has_syntax = syntax_present(curwin);
+#endif
+    int         (*func) __ARGS((pos_T *));
+    int         found = FALSE;
+    int         r;
+
+#ifdef FEAT_SYN_HL
+    if (has_syntax && attr != NULL)
+    {
+	pos = curwin->w_cursor;
+
+	if (dir == FORWARD)
+	  func = inc;
+	else
+	  func = dec;
+
+	while (count--)
+	{
+	    while (check_syn_id((pos_T *) &pos, attr))
+	    {
+		/* if the cursor is already at the highlighting group,
+		*  move over it first, but stop at line boundaries
+		*/
+	        r = (*func)(&pos);
+		if (r == -1)
+		    return FAIL;
+		if (r == 1)
+		  break;
+	    }
+	    for (;;)
+	    {
+	        found  = check_syn_id((pos_T *) &pos, attr);
+		if (!found)
+		{
+		    if ((*func)(&pos) == -1)
+		    /* Stop at end of file or start of file*/
+			return FAIL;
+		}
+		else
+		  break;
+	    }
+	}
+	if (found)
+	{
+#if 0
+	    /* Move to the beginning of the syntax highlighting.
+	     * Disabled currenty, because positinioning the 
+	     * cursor at the end of the highlight group happens
+	     * on purpose
+	     * */
+	    if (dir == BACKWARD)
+	    {
+		while (check_syn_id((pos_T *) &pos, attr))
+		{
+		    /* if the cursor is already at an error,
+		    * move over it first
+		    */
+		    if ((*func)(&pos) == -1)
+		    return FAIL;
+		}
+		inc(&pos);
+	    }
+#endif
+	    setpcmark();
+	    curwin->w_cursor = pos;
+	    adjust_cursor_col();
+	    return found;
+	}
+	else
+	    return FAIL;
+    }
+    else
+#endif
+        return FAIL;
+}
diff --git a/src/option.c b/src/option.c
--- a/src/option.c
+++ b/src/option.c
@@ -125,6 +125,9 @@
 #endif
 #define PV_INF		OPT_BUF(BV_INF)
 #define PV_ISK		OPT_BUF(BV_ISK)
+#ifdef FEAT_SYN_HL
+#define PV_JHL		OPT_BUF(BV_JHL)
+#endif
 #ifdef FEAT_CRYPT
 # define PV_KEY		OPT_BUF(BV_KEY)
 #endif
@@ -354,6 +357,7 @@
 #ifdef FEAT_SYN_HL
 static long	p_smc;
 static char_u	*p_syn;
+static char_u   *p_jhl;
 #endif
 #ifdef FEAT_SPELL
 static char_u	*p_spc;
@@ -1579,6 +1583,15 @@
     {"joinspaces",  "js",   P_BOOL|P_VI_DEF|P_VIM,
 			    (char_u *)&p_js, PV_NONE,
 			    {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT},
+    {"jumphlgroup", "jhl",  P_STRING|P_ALLOCED|P_VIM|P_COMMA|P_NODUP,
+#ifdef FEAT_SYN_HL
+			    (char_u *)&p_jhl, PV_JHL,
+			    {(char_u *)"", (char_u *)"Error"}
+#else
+			    (char_u *)NULL, PV_NONE,
+			    {(char_u *)0L, (char_u *)0L}
+#endif
+			    SCRIPTID_INIT},
     {"key",	    NULL,   P_STRING|P_ALLOCED|P_VI_DEF|P_NO_MKRC,
 #ifdef FEAT_CRYPT
 			    (char_u *)&p_key, PV_KEY,
@@ -5261,6 +5274,7 @@
 #endif
 #ifdef FEAT_SYN_HL
     check_string_option(&buf->b_p_syn);
+    check_string_option(&buf->b_p_jhl);
 #endif
 #ifdef FEAT_SPELL
     check_string_option(&buf->b_s.b_p_spc);
@@ -5674,6 +5688,9 @@
     /* 'colorcolumn' */
     else if (varp == &curwin->w_p_cc)
 	errmsg = check_colorcolumn(curwin);
+    /* 'jumphlgrp' */
+    else if (gvarp == &p_jhl)
+	errmsg = check_syntaxgroups(curbuf);
 #endif
 
 #ifdef FEAT_MULTI_LANG
@@ -6955,6 +6972,9 @@
 	{
 	    apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn,
 					       curbuf->b_fname, TRUE, curbuf);
+	    if (curbuf->b_p_jhl)
+	        /* Add new syntaxgroups to check for */
+		check_syntaxgroups(curbuf);
 	}
 # endif
 	else if (varp == &(curbuf->b_p_ft))
@@ -7021,6 +7041,83 @@
     return *(const int *)a - *(const int *)b;
 }
 
+#ifdef FEAT_SYN_HL
+/*
+ * Handle the 'jumphlgroup' setting, returns error message, NULL if
+ * it is OK
+ */
+
+    char_u *
+check_syntaxgroups(buf)
+    buf_T *buf;
+{
+    char_u *s, *p;
+    char_u *r = NULL;
+    int	    count = -1;
+    int     ids[256];
+    int     i = 0;
+    int     j = 0;
+
+    s = buf->b_p_jhl;
+    p = (char_u *)alloc((unsigned)sizeof(char_u *) * (STRLEN(buf->b_p_jhl)));
+    STRMOVE(p, buf->b_p_jhl);
+
+    while (count < 255)
+    {
+      if (*s != ',' && *s != NUL && s != NULL)
+	i++;
+      else
+      {
+	STRMOVE(p,s-i);
+	p[i] = NUL;
+	ids[++count] = syn_name2id(p);
+	/* Don't check syntaxgroups, the may be defined later
+	 * when the syntax autocommand is executed
+	 * Assume, all will be valid.
+	 *
+	if (ids[count] == 0)
+	{
+	    r =  e_invarg;
+	    break;
+	} */
+	if (*s == NUL || s == NULL)
+	  break;
+	s = skip_to_option_part(s);
+	i = 1;
+      }
+      s++;
+    }
+
+    count++;
+    vim_free(buf->b_p_jhlids);
+    if ( count > 0 )
+    {
+	buf->b_p_jhlids = (int *)alloc((unsigned)sizeof(int) * (count + 1));
+	if (buf->b_p_jhlids != NULL)
+	{
+	    /* sort the columns to elimnate duplicates */
+	    qsort(ids, count, sizeof(int), int_cmp);
+
+	    for (i = 0; i < count; ++i)
+		/* skip duplicates 
+	         * and only include valid syntax groups
+		 **/
+		if ( ids[i] > 0 
+		    && (j == 0 || buf->b_p_jhlids[j - 1] != ids[i]))
+		    buf->b_p_jhlids[j++] = ids[i];
+	    buf->b_p_jhlids[j] = -1;  /* end marker */
+	}
+
+    }
+    else
+      buf->b_p_jhlids=NULL;
+
+    vim_free(p);
+    return r;
+
+}
+#endif 
+
 /*
  * Handle setting 'colorcolumn' or 'textwidth' in window "wp".
  * Returns error message, NULL if it's OK.
@@ -9535,6 +9632,7 @@
 	case PV_CUC:	return (char_u *)&(curwin->w_p_cuc);
 	case PV_CUL:	return (char_u *)&(curwin->w_p_cul);
 	case PV_CC:	return (char_u *)&(curwin->w_p_cc);
+	case PV_JHL:	return (char_u *)&(curbuf->b_p_jhl);
 #endif
 #ifdef FEAT_DIFF
 	case PV_DIFF:	return (char_u *)&(curwin->w_p_diff);
@@ -10018,6 +10116,8 @@
 	    /* Don't copy 'syntax', it must be set */
 	    buf->b_p_syn = empty_option;
 	    buf->b_p_smc = p_smc;
+	    buf->b_p_jhl = vim_strsave(p_jhl);
+	    (void)check_syntaxgroups(buf);
 #endif
 #ifdef FEAT_SPELL
 	    buf->b_s.b_p_spc = vim_strsave(p_spc);
diff --git a/src/option.h b/src/option.h
--- a/src/option.h
+++ b/src/option.h
@@ -1005,6 +1005,7 @@
 #ifdef FEAT_SYN_HL
     , BV_SMC
     , BV_SYN
+    , BV_JHL
 #endif
 #ifdef FEAT_SPELL
     , BV_SPC
diff --git a/src/proto/option.pro b/src/proto/option.pro
--- a/src/proto/option.pro
+++ b/src/proto/option.pro
@@ -56,4 +56,7 @@
 void save_file_ff __ARGS((buf_T *buf));
 int file_ff_differs __ARGS((buf_T *buf, int ignore_empty));
 int check_ff_value __ARGS((char_u *p));
+#ifdef FEAT_SYN_HL
+char_u *check_syntaxgroups __ARGS((buf_T *buf));
+#endif
 /* vim: set ft=c : */
diff --git a/src/proto/syntax.pro b/src/proto/syntax.pro
--- a/src/proto/syntax.pro
+++ b/src/proto/syntax.pro
@@ -19,6 +19,7 @@
 int syn_get_sub_char __ARGS((void));
 int syn_get_stack_item __ARGS((int i));
 int syn_get_foldlevel __ARGS((win_T *wp, long lnum));
+int check_syn_id __ARGS((pos_T *found_pos, int *synid));
 void init_highlight __ARGS((int both, int reset));
 int load_colors __ARGS((char_u *name));
 void do_highlight __ARGS((char_u *line, int forceit, int init));
diff --git a/src/structs.h b/src/structs.h
--- a/src/structs.h
+++ b/src/structs.h
@@ -1518,6 +1518,10 @@
     char_u	*b_p_fex;	/* 'formatexpr' */
     long_u	b_p_fex_flags;	/* flags for 'formatexpr' */
 #endif
+#ifdef FEAT_SYN_HL
+    char_u      *b_p_jhl;	/* 'jumphighlight' */
+    int         *b_p_jhlids;    /* array for 'jumphighlight' ids */
+#endif
 #ifdef FEAT_CRYPT
     char_u	*b_p_key;	/* 'key' */
 #endif
diff --git a/src/syntax.c b/src/syntax.c
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -6471,6 +6471,79 @@
 }
 #endif
 
+/* 
+ * Check whether the given syntax id matches
+ * at the specified position (follows links)
+ */
+
+    int
+check_syn_id(found_pos, synid)
+    pos_T       *found_pos;
+    int         *synid;
+{
+    int         t_attr;
+    struct hl_group *c_attr;
+    int         found = FAIL;
+    int         count = 0;
+    match_T     *match;
+    matchitem_T *cur;
+
+    if (synid == NUL)
+      return FALSE;
+
+    t_attr = syn_get_id(curwin, found_pos->lnum, found_pos->col,
+	    TRUE, NULL, FALSE);
+    if (!t_attr)
+      return FALSE;
+
+    c_attr = &HL_TABLE()[t_attr - 1];
+    /* Don't know, why a syntax attribute can't have a
+    * name, but a link, but check here anyways to avoid a crash
+    * */
+    while ( c_attr->sg_name != NUL && c_attr->sg_link != 0)
+    {
+        for (count = 0; count < 255 && synid[count] > -1; count++)
+	{
+	  if (t_attr == synid[count])
+	  {
+	    found = TRUE;
+	    break;
+	  }
+	}
+	if (found)
+	  break;
+	else
+	{
+	    t_attr = c_attr->sg_link;
+	    c_attr = &HL_TABLE()[t_attr-1];
+	}
+    }
+
+    for (count = 0; count < 255 && synid[count] > -1; count++)
+    {
+      if (t_attr == synid[count])
+      {
+	found = TRUE;
+	break;
+      }
+    }
+
+    return found;
+}
+
 #endif /* FEAT_SYN_HL */
 
 /**************************************

Raspunde prin e-mail lui