Loading ...
Sorry, an error occurred while loading the content.

Regex problem in syntax description

Expand Messages
  • Corinna Vinschen
    Hi, this is using vim60at. I m trying to optimize the syntax file `changelog.vim and I stumbled over a problem. The highlighting of an expression is not what
    Message 1 of 6 , Aug 31, 2001
    • 0 Attachment
      Hi,

      this is using vim60at.

      I'm trying to optimize the syntax file `changelog.vim' and I
      stumbled over a problem. The highlighting of an expression is
      not what I expect from my regular expression.

      Typical ChangeLog entry looks like

      * file: description.
      * file (function): description.
      * file (class::method): description.

      or followup lines w/o a star:

      (function): description.
      (class::method): description.

      The highlighting should highlight the part up to the colon right
      before the descriptive text. Sometimes a `+' is used instead of
      `*' or brackets instead of parens.

      Now consider the following two entries from the GDB ChangeLog file:

      * config/xm-lynx.h, config/xm-nbsd.h, config/xm-sysv4.h,
      config/i386/xm-i386aix.h, config/m68k/xm-dpx2.h: Remove redundant
      inclusion of <limits.h>.

      * utils.c (get_field, floatformat_to_doublest, put_field)
      (ldfrexp, floatformat_from_doublest, floatformat_is_negative)
      (floatformat_is_nan, floatformat_mantissa)
      (FLOATFORMAT_CHAR_BIT): Move from here.

      The first example represents a `file' entry while the second
      example represents a `file (function)' entry. Now, these entries
      are multiline entries where the highlighting should still go from
      the `*' up to the colon in line 2 resp. line 4.

      This isn't handled by the current version of the changelog.vim file
      so I tried to fix the corresponding regular expression but... it
      doesn't work.

      The expressions I'm using to describe entries are the following:

      Standard entries:

      syn match changelogFiles "^\s\+[+*]\s\+\_.\{-}:\s"

      Followup lines:

      syn match changeLogFuncs contained "^\s\+[([]\_.\{-}:\s"

      Surprise, the first example is only highlighted in the first line,
      while the second example is highlighted correctly up to the colon
      in line 4.

      Does somebody have a clue why that happens? Is my regex wrong to
      reflect the first example? I can't find the error :-(

      Corinna

      --
      Corinna Vinschen
      Cygwin Developer
      Red Hat, Inc.
      mailto:vinschen@...
    • Preben Guldberg
      ... It does appear that way... Actually, the match statements must be within one line ( :help syn-define ). So changelogFiles matches the first line, and in
      Message 2 of 6 , Sep 3, 2001
      • 0 Attachment
        Thus wrote Corinna Vinschen (vinschen@...) on [010901]:

        > The expressions I'm using to describe entries are the following:

        > Standard entries:

        > syn match changelogFiles "^\s\+[+*]\s\+\_.\{-}:\s"

        > Followup lines:

        > syn match changeLogFuncs contained "^\s\+[([]\_.\{-}:\s"

        > Surprise, the first example is only highlighted in the first line,
        > while the second example is highlighted correctly up to the colon
        > in line 4.

        It does appear that way...

        Actually, the "match" statements must be within one line (":help
        syn-define"). So changelogFiles matches the first line, and in the
        second example changeLogFuncs matches each of the following line
        (three matches).

        If you want multilines, why not go for something like

        syn region changelogFiles start='^\s\+[+*]' end=':' contains=changeLogFuncs
        syn region changeLogFuncs contained start='(' end=')'
        syn region changeLogFuncs contained start='[' end=']'

        or, if parens are not allow to nest or span lines

        syn region changelogFiles start='^\s\+[+*]' end=':' contains=changeLogFuncs
        syn match changeLogFuncs '[[(].\{-}[)\]]'

        There is probably an issue with filenames that contain one of "[()]".

        Peppe
        --
        "Before you criticize someone, walk
        Preben "Peppe" Guldberg __/-\__ a mile in his shoes. That way, if
        c928400@... (o o) he gets angry, he'll be a mile away
        ----------------------oOOo (_) oOOo-- - and barefoot." --Sarah Jackson
      • Corinna Vinschen
        ... Thanks for all these hints. They have helped very much. I have send a new version of changelog.vim to Bram a few minutes ago. Corinna -- Corinna Vinschen
        Message 3 of 6 , Sep 3, 2001
        • 0 Attachment
          On Mon, Sep 03, 2001 at 09:54:16AM +0200, Preben Guldberg wrote:
          > Thus wrote Corinna Vinschen (vinschen@...) on [010901]:
          >
          > > The expressions I'm using to describe entries are the following:
          >
          > > Standard entries:
          >
          > > syn match changelogFiles "^\s\+[+*]\s\+\_.\{-}:\s"
          >
          > > Followup lines:
          >
          > > syn match changeLogFuncs contained "^\s\+[([]\_.\{-}:\s"
          >
          > > Surprise, the first example is only highlighted in the first line,
          > > while the second example is highlighted correctly up to the colon
          > > in line 4.
          >
          > It does appear that way...
          >
          > Actually, the "match" statements must be within one line (":help
          > syn-define"). So changelogFiles matches the first line, and in the
          > second example changeLogFuncs matches each of the following line
          > (three matches).
          >
          > If you want multilines, why not go for something like
          >
          > syn region changelogFiles start='^\s\+[+*]' end=':' contains=changeLogFuncs
          > syn region changeLogFuncs contained start='(' end=')'
          > syn region changeLogFuncs contained start='[' end=']'
          >
          > or, if parens are not allow to nest or span lines
          >
          > syn region changelogFiles start='^\s\+[+*]' end=':' contains=changeLogFuncs
          > syn match changeLogFuncs '[[(].\{-}[)\]]'
          >
          > There is probably an issue with filenames that contain one of "[()]".

          Thanks for all these hints. They have helped very much. I have send
          a new version of changelog.vim to Bram a few minutes ago.

          Corinna

          --
          Corinna Vinschen
          Cygwin Developer
          Red Hat, Inc.
          mailto:vinschen@...
        • Bram Moolenaar
          ... Although it is true that originally a match would only work within one line, that comes from the time that a regexp pattern could not span more than one
          Message 4 of 6 , Sep 3, 2001
          • 0 Attachment
            Preben Peppe Guldberg wrote:

            > Thus wrote Corinna Vinschen (vinschen@...) on [010901]:
            >
            > > The expressions I'm using to describe entries are the following:
            > >
            > > Standard entries:
            > >
            > > syn match changelogFiles "^\s\+[+*]\s\+\_.\{-}:\s"
            > >
            > > Followup lines:
            > >
            > > syn match changeLogFuncs contained "^\s\+[([]\_.\{-}:\s"
            > >
            > > Surprise, the first example is only highlighted in the first line,
            > > while the second example is highlighted correctly up to the colon
            > > in line 4.
            >
            > It does appear that way...
            >
            > Actually, the "match" statements must be within one line (":help
            > syn-define"). So changelogFiles matches the first line, and in the
            > second example changeLogFuncs matches each of the following line
            > (three matches).

            Although it is true that originally a "match" would only work within one
            line, that comes from the time that a regexp pattern could not span more
            than one line. It would now be possible to let the "match" item span
            more than one line. That is in fact a good way to find specific items.
            Using a region quickly makes it more complicated.

            I made a change recently to avoid that a match with a contained item
            would continue when the contained items ends. But this was done a bit
            drastically, it also truncates any match that spans more than one line.
            It seems it is quite easy to avoid this and make the example above work.

            Please try this patch. It does work for the example above, but this
            code is very complicated, it's hard to predict if there now is another
            situation where it fails.

            *** ../vim-6.0au/src/syntax.c Sun Sep 2 19:29:02 2001
            --- src/syntax.c Mon Sep 3 12:36:47 2001
            ***************
            *** 940,951 ****

            if (startofline)
            {
            ! /* A match carried over from a previous line must have a contained
            ! * region. The match ends as soon as the region ends. */
            for (i = 0; i < current_state.ga_len; ++i)
            {
            cur_si = &CUR_STATE(i);
            ! if ((SYN_ITEMS(syn_buf)[cur_si->si_idx]).sp_type == SPTYPE_MATCH)
            {
            cur_si->si_flags |= HL_MATCHCONT;
            cur_si->si_m_endpos.lnum = 0;
            --- 940,952 ----

            if (startofline)
            {
            ! /* Check for a match carried over from a previous line with a
            ! * contained region. The match ends as soon as the region ends. */
            for (i = 0; i < current_state.ga_len; ++i)
            {
            cur_si = &CUR_STATE(i);
            ! if ((SYN_ITEMS(syn_buf)[cur_si->si_idx]).sp_type == SPTYPE_MATCH
            ! && cur_si->si_m_endpos.lnum < current_lnum)
            {
            cur_si->si_flags |= HL_MATCHCONT;
            cur_si->si_m_endpos.lnum = 0;

            --
            Life is a gift, living is an art. (Bram Moolenaar)

            /// Bram Moolenaar -- Bram@... -- http://www.moolenaar.net \\\
            ((( Creator of Vim -- http://vim.sf.net -- ftp://ftp.vim.org/pub/vim )))
            \\\ Help me helping AIDS orphans in Uganda - http://iccf-holland.org ///
          • Preben Guldberg
            ... For existing text it seems to work just fine. However, when entering new text, the highlighting is only updated if a potentially multiline pattern is
            Message 5 of 6 , Sep 3, 2001
            • 0 Attachment
              Thus wrote Bram Moolenaar (Bram@...) on [010903]:

              > Please try this patch. It does work for the example above, but this
              > code is very complicated, it's hard to predict if there now is another
              > situation where it fails.

              For existing text it seems to work just fine.

              However, when entering new text, the highlighting is only updated if
              a potentially multiline pattern is matched in a single line.

              Try these few lines:

              :syn clear
              :syn match Todo "^\s\+[+*]\s\+\zs\_.\{-}\ze:\s" contains=Error
              :syn match Error contained "(\_.\{-})"

              Test case:

              * utils.c (get_field, floatformat_to_doublest, put_field)
              (ldfrexp, floatformat_from_doublest, floatformat_is_negative)
              (floatformat_is_nan, floatformat_mantissa)
              (FLOATFORMAT_CHAR_BIT): Move from here.

              The highlighting is fine, but try and insert a snippet like

              * utils.c (foo)
              (bar): testing

              [syn-sync-minlines does not remedy this, more below]

              Also, if you edit the existing text (eg. "Ax<ESC>") on a line other
              than the first in the multiline, the highlighting disappears from that
              line onwards. If one at this point escapes, go to the first line and
              inserts some text, the currently highlighted lines plus one will be
              highlighted (not all, just one more).

              Using "syn sync minlines=X", the first (2*X + 1) lines of an existing
              multiline match will be highlighted correctly at all times (or so it
              seems in a few tests).

              Not sure if I have hit some internal limits wrt. syn-sync or multiline
              patterns, though.

              Peppe
              --
              "Before you criticize someone, walk
              Preben "Peppe" Guldberg __/-\__ a mile in his shoes. That way, if
              c928400@... (o o) he gets angry, he'll be a mile away
              ----------------------oOOo (_) oOOo-- - and barefoot." --Sarah Jackson
            • Bram Moolenaar
              ... That s normal. Since the match depends on where you start looking for the pattern, you need to add something for synchonizing. A simple ... Explanation:
              Message 6 of 6 , Sep 3, 2001
              • 0 Attachment
                Preben Peppe Guldberg wrote:

                > Thus wrote Bram Moolenaar (Bram@...) on [010903]:
                >
                > > Please try this patch. It does work for the example above, but this
                > > code is very complicated, it's hard to predict if there now is another
                > > situation where it fails.
                >
                > For existing text it seems to work just fine.
                >
                > However, when entering new text, the highlighting is only updated if
                > a potentially multiline pattern is matched in a single line.

                That's normal. Since the match depends on where you start looking for
                the pattern, you need to add something for synchonizing. A simple
                solution would be to do:

                :syn sync minlines=20

                Explanation: Vim starts redrawing where you made a change. That's where
                it starts looking for syntax items. Only regions are remembered in the
                cache, not matches.

                --
                TIM: That is not an ordinary rabbit ... 'tis the most foul cruel and
                bad-tempered thing you ever set eyes on.
                ROBIN: You tit. I soiled my armour I was so scared!
                "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

                /// Bram Moolenaar -- Bram@... -- http://www.moolenaar.net \\\
                ((( Creator of Vim -- http://vim.sf.net -- ftp://ftp.vim.org/pub/vim )))
                \\\ Help me helping AIDS orphans in Uganda - http://iccf-holland.org ///
              Your message has been successfully submitted and would be delivered to recipients shortly.