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

Function to complete #if's

Expand Messages
  • Mark Zealey
    As you ll know, when editing a C file, when you put a {, and then a matching }, you can make vim move the cursor momenterally to the matching {. I am wondering
    Message 1 of 10 , Aug 1, 2001
      As you'll know, when editing a C file, when you put a {, and then a matching },
      you can make vim move the cursor momenterally to the matching {. I am wondering
      if the same could be done with #if/#else/#endif preprocessor macros, and further
      more do something like:

      #ifdef __foo__
      ...
      #else
      ...
      #endif

      And vim could automatically fill in the #else and #endif with /* __foo__ */
      after them, as is commonly the style in complexed .h files.

      Taking this a bit further, it could be possible to do the same with #if:
      #if defined(__foo__) && !defined(__bar__)

      and on the #else and #endif, vim would automatically put /* defined(__foo__) &&
      !defined(__bar__) */ after it.

      Would any of this be possible, and how? :-)

      TIA

      --

      Mark Zealey (aka JALH on irc.openprojects.net: #zealos and many more)
      mark@...

      UL++++>$ G!>(GCM/GCS/GS/GM) dpu? s:-@ a16! C++++>$ P++++>+++++$ L+++>+++++$
      !E---? W+++>$ N- !o? !w--- O? !M? !V? !PS !PE--@ PGP+? r++ !t---?@ !X---?
      !R- b+ !tv b+ DI+ D+? G+++ e>+++++ !h++* r!-- y--

      (www.geekcode.com)
    • Edwin
      ... There is a script that Benji Fisher wrote and placed at: http://vim.sourceforge.net/scripts/script.php?script_id=39 just source the matchit.vim file from
      Message 2 of 10 , Aug 1, 2001
        --- Mark Zealey <mark@...> wrote:
        > As you'll know, when editing a C file, when you put a {, and then a
        > matching },
        > you can make vim move the cursor momenterally to the matching {. I am
        > wondering
        > if the same could be done with #if/#else/#endif preprocessor macros,

        There is a script that Benji Fisher wrote and placed at:

        http://vim.sourceforge.net/scripts/script.php?script_id=39
        just source the matchit.vim file from within your .vimrc
        and it should work.

        '%' will then be able to match more than one character.

        As for the rest below, you will probably have to write
        a small function to do this.

        Good luck,
        Edwin-

        > and further
        > more do something like:
        >
        > #ifdef __foo__
        > ...
        > #else
        > ...
        > #endif
        >
        > And vim could automatically fill in the #else and #endif with /*
        > __foo__ */
        > after them, as is commonly the style in complexed .h files.
        >
        > Taking this a bit further, it could be possible to do the same with
        > #if:
        > #if defined(__foo__) && !defined(__bar__)
        >
        > and on the #else and #endif, vim would automatically put /*
        > defined(__foo__) &&
        > !defined(__bar__) */ after it.
        >
        > Would any of this be possible, and how? :-)
        >
        > TIA
        >
        > --
        >
        > Mark Zealey (aka JALH on irc.openprojects.net: #zealos and many more)
        > mark@...
        >
        > UL++++>$ G!>(GCM/GCS/GS/GM) dpu? s:-@ a16! C++++>$ P++++>+++++$
        > L+++>+++++$
        > !E---? W+++>$ N- !o? !w--- O? !M? !V? !PS !PE--@ PGP+? r++ !t---?@
        > !X---?
        > !R- b+ !tv b+ DI+ D+? G+++ e>+++++ !h++* r!-- y--
        >
        > (www.geekcode.com)


        __________________________________________________
        Do You Yahoo!?
        Make international calls for as low as $.04/minute with Yahoo! Messenger
        http://phonecard.yahoo.com/
      • Jeff Walker
        Well, vim5 already bounces between #if/#else/#endif, without using Benji s excellent script. Perhaps there s a setting that I forgot that I set a long time
        Message 3 of 10 , Aug 1, 2001
          Well, vim5 already bounces between #if/#else/#endif, without using Benji's
          excellent script.

          Perhaps there's a setting that I forgot that I set a long time ago, but I
          don't think so.

          As for the other, I don't know. Certainly doable, just lazy/busy.

          --
          Jeff Walker MatchLogic, Inc.
          jwalker@... 7233 Church Ranch Blvd.
          Voice 1 (303) 222-2105 Westminster, CO 80021
          Fax 1 (303) 222-2001 www.matchlogic.com


          -----Original Message-----
          From: Edwin [mailto:incaic@...]
          Sent: Wednesday, August 01, 2001 12:47 PM
          To: Mark Zealey; vim@...
          Subject: Re: Function to complete #if's



          --- Mark Zealey <mark@...> wrote:
          > As you'll know, when editing a C file, when you put a {, and then a
          > matching },
          > you can make vim move the cursor momenterally to the matching {. I am
          > wondering
          > if the same could be done with #if/#else/#endif preprocessor macros,

          There is a script that Benji Fisher wrote and placed at:

          http://vim.sourceforge.net/scripts/script.php?script_id=39
          just source the matchit.vim file from within your .vimrc
          and it should work.

          '%' will then be able to match more than one character.

          As for the rest below, you will probably have to write
          a small function to do this.

          Good luck,
          Edwin-

          > and further
          > more do something like:
          >
          > #ifdef __foo__
          > ...
          > #else
          > ...
          > #endif
          >
          > And vim could automatically fill in the #else and #endif with /*
          > __foo__ */
          > after them, as is commonly the style in complexed .h files.
          >
          > Taking this a bit further, it could be possible to do the same with
          > #if:
          > #if defined(__foo__) && !defined(__bar__)
          >
          > and on the #else and #endif, vim would automatically put /*
          > defined(__foo__) &&
          > !defined(__bar__) */ after it.
          >
          > Would any of this be possible, and how? :-)
          >
          > TIA
          >
          > --
          >
          > Mark Zealey (aka JALH on irc.openprojects.net: #zealos and many more)
          > mark@...
          >
          > UL++++>$ G!>(GCM/GCS/GS/GM) dpu? s:-@ a16! C++++>$ P++++>+++++$
          > L+++>+++++$
          > !E---? W+++>$ N- !o? !w--- O? !M? !V? !PS !PE--@ PGP+? r++ !t---?@
          > !X---?
          > !R- b+ !tv b+ DI+ D+? G+++ e>+++++ !h++* r!-- y--
          >
          > (www.geekcode.com)


          __________________________________________________
          Do You Yahoo!?
          Make international calls for as low as $.04/minute with Yahoo! Messenger
          http://phonecard.yahoo.com/
        • Mark Zealey
          ... [Nice script cut] Thanks! here s a slightly fixed version which works with #ifndef too. preprocessor macro s can t have whitepsace before the # however, I
          Message 4 of 10 , Aug 1, 2001
            On Wed, Aug 01, 2001 at 09:48:50PM +0300, Bohdan Vlasyuk wrote:

            > On Wed, Aug 01, 2001 at 07:38:10PM +0100, Mark Zealey wrote:
            >
            > > And vim could automatically fill in the #else and #endif with /* __foo__ */
            > > after them, as is commonly the style in complexed .h files.

            [Nice script cut]


            Thanks! here's a slightly fixed version which works with #ifndef too.
            preprocessor macro's can't have whitepsace before the # however, I believe, so I
            fixed that:

            fun SetPreproc()
            mark j
            if match(getline('.'), '^#\s*endif\s*') != -1
            normal %
            let cond = ''
            let line = getline('.')

            let c_start = matchend(line, '^#\s*if\s\+')
            if c_start != -1
            let cond = strpart(line, c_start)
            endif

            let c_start = matchend(line, '^#\s*ifdef\s\+')
            if c_start != -1
            let cond = strpart(line, c_start)
            endif

            let c_start = matchend(line, '^#\s*ifndef\s\+')
            if c_start != -1
            let cond = '!' . strpart(line, c_start)
            endif

            if cond != ''
            normal %
            if match(getline('.'), '^#\s*else') != -1
            exec 'normal A /* ' . cond . ' */'
            normal ^%
            endif
            exec 'normal A /* ' . cond . ' */'
            endif
            endif
            'j
            endfun

            inoremap #endif #endif<C-O>:call SetPreproc()<CR>


            --

            Mark Zealey (aka JALH on irc.openprojects.net: #zealos and many more)
            mark@...

            UL++++>$ G!>(GCM/GCS/GS/GM) dpu? s:-@ a16! C++++>$ P++++>+++++$ L+++>+++++$
            !E---? W+++>$ N- !o? !w--- O? !M? !V? !PS !PE--@ PGP+? r++ !t---?@ !X---?
            !R- b+ !tv b+ DI+ D+? G+++ e>+++++ !h++* r!-- y--

            (www.geekcode.com)
          • Bohdan Vlasyuk
            ... Ok. sorry that no explaination followed (was it working at all??) -- it was 14-th hour of my sitting in front of computed, and I somewhat hurried to leave.
            Message 5 of 10 , Aug 2, 2001
              On Wed, Aug 01, 2001 at 08:29:22PM +0100, Mark Zealey wrote:

              >>> And vim could automatically fill in the #else and #endif with /*
              >>> __foo__ */
              >> [Nice script cut]
              > Thanks! here's a slightly fixed version which works with #ifndef
              > too.
              Ok. sorry that no explaination followed (was it working at all??) --
              it was 14-th hour of my sitting in front of computed, and I somewhat
              hurried to leave.

              > fun SetPreproc()

              [skip]
              > let line = getline('.')
              > let c_start = matchend(line, '^#\s*if\s\+')
              > let c_start = matchend(line, '^#\s*ifdef\s\+')
              > let c_start = matchend(line, '^#\s*ifndef\s\+')
              this can be changed to one line
              let c_start = matchend(line, '^#\s*if\(n\=def\)\=\s\+')
              however, three `if's have that advantage that you can specify
              different strings for different cases, e.g.:
              #if foo
              ...
              #ednif /* if foo */

              #ifdef foo
              ...
              #endif /* ifdef foo */

              etc...


              > if cond != ''
              > normal %
              > if match(getline('.'), '^#\s*else') != -1
              > exec 'normal A /* ' . cond . ' */'
              > normal ^%
              > endif
              > exec 'normal A /* ' . cond . ' */'
              this can be turned into while loop, matching for #endif, but while
              loop is not safe, if your % is broken, and would lead you to place
              where there would be no return..

              > inoremap #endif #endif<C-O>:call SetPreproc()<CR>
              I suppose you'd better make it abbreviation, see :h Abbreviations for
              details...



              --
              "You know, of course, that the Tasmanians, who never committed adultery, are
              now extinct."
              - M. Somerset Maugham
            • Benji Fisher
              ... [snip] I could add functionality like this to my script matchit.vim. The problem of automatically generating #endif from #if is similar to the problem of
              Message 6 of 10 , Aug 2, 2001
                Bohdan Vlasyuk wrote:
                >
                > On Wed, Aug 01, 2001 at 08:29:22PM +0100, Mark Zealey wrote:
                >
                > >>> And vim could automatically fill in the #else and #endif with /*
                > >>> __foo__ */
                > >> [Nice script cut]
                > > Thanks! here's a slightly fixed version which works with #ifndef
                > > too.
                [snip]

                I could add functionality like this to my script matchit.vim. The
                problem of automatically generating #endif from #if is similar to the problem
                of using % to jump between the two. (This much is already in standard vim,
                but matchit.vim allows you to customize the behavior for different
                languages.) The only reason I have not done this already is that it is hard,
                given the regular expressions that match <tag> and </tag> (where the "tag"
                text can be anything), it is difficult to generate the string "</tag>". One
                way to solve this is to have separate sets of patterns for % matching and for
                completion.

                My idea is to allow the user to map a key, such as <C-Enter>, to call the
                function that generates the closing string. I am not sure how to handle
                "else"-like strings...

                --Benji Fisher
              • Bohdan Vlasyuk
                ... I think if you can generate #endif, it also means that you re able to find corresponding #if. [That looks obvious] ... If I got it right, you re talking
                Message 7 of 10 , Aug 2, 2001
                  On Thu, Aug 02, 2001 at 09:31:04AM -0400, Benji Fisher wrote:

                  > The problem of automatically generating #endif from #if is similar
                  > to the problem of using % to jump between the two.
                  I think if you can generate #endif, it also means that you're able to
                  find corresponding #if. [That looks obvious]

                  > The only reason I have not done this already is that it is hard,
                  > given the regular expressions that match <tag> and </tag>, it is
                  > difficult to generate the string "</tag>". One way to solve this is
                  > to have separate sets of patterns for % matching and for completion.
                  > My idea is to allow the user to map a key, such as <C-Enter>, to
                  > call the function that generates the closing string. I am not sure
                  > how to handle "else"-like strings...
                  If I got it right, you're talking about thing different from that what
                  was originally supposed -- you mean to generate closing strings, not
                  comments to already given strings..

                  As far as I understand how it would work, I assume this may be
                  misleading.. I think you search backwards for anything that looks like
                  closing/opening tag, and skip to corresponding opening tag in case of
                  closing, and generate closing tag if you've met opening tag.. Is it
                  correct ??

                  In the context of html, how would you deal with <p> and other which
                  are not neccesary closed ??


                  --
                  The luck that is ordained for you will be coveted by others.
                • Benji Fisher
                  ... Right. The point is, one of these problems has already been solved, in matchit.vim . It is not much additional work to solve the other one. ... Right.
                  Message 8 of 10 , Aug 2, 2001
                    Bohdan Vlasyuk wrote:
                    >
                    > On Thu, Aug 02, 2001 at 09:31:04AM -0400, Benji Fisher wrote:
                    >
                    > > The problem of automatically generating #endif from #if is similar
                    > > to the problem of using % to jump between the two.
                    > I think if you can generate #endif, it also means that you're able to
                    > find corresponding #if. [That looks obvious]

                    Right. The point is, one of these problems has already been solved, in
                    matchit.vim . It is not much additional work to solve the other one.

                    > > The only reason I have not done this already is that it is hard,
                    > > given the regular expressions that match <tag> and </tag>, it is
                    > > difficult to generate the string "</tag>". One way to solve this is
                    > > to have separate sets of patterns for % matching and for completion.
                    > > My idea is to allow the user to map a key, such as <C-Enter>, to
                    > > call the function that generates the closing string. I am not sure
                    > > how to handle "else"-like strings...
                    > If I got it right, you're talking about thing different from that what
                    > was originally supposed -- you mean to generate closing strings, not
                    > comments to already given strings..

                    Right.

                    > As far as I understand how it would work, I assume this may be
                    > misleading.. I think you search backwards for anything that looks like
                    > closing/opening tag, and skip to corresponding opening tag in case of
                    > closing, and generate closing tag if you've met opening tag.. Is it
                    > correct ??

                    Not quite. When I hit <C-Enter> (or whatever other key I have chosen)
                    the script looks back to find an unclosed "<tag>", say. It does not actually
                    move the cursor, though, which is how I would understand your "skip". The
                    script would add "</tag>" at the cursor position.

                    > In the context of html, how would you deal with <p> and other which
                    > are not neccesary closed ??

                    For each language, someone has to decide what matching patterns would be
                    used. For HTML, one might decide to ignore "<p>".

                    --Benji Fisher
                  • Bohdan Vlasyuk
                    ... I mean: if you have ... and press , what would you have then ?? I think it woule be natural to get , wouldn t
                    Message 9 of 10 , Aug 2, 2001
                      In Thu, Aug 02, 2001 at 11:09:14PM -0400, Benji Fisher wrote:

                      >> I think you search backwards for anything that looks like
                      >> closing/opening tag, and skip to corresponding opening tag in case
                      >> of closing, and generate closing tag if you've met opening tag.. Is
                      >> it correct ??
                      > Not quite. When I hit <C-Enter> (or whatever other key I have
                      > chosen) the script looks back to find an unclosed "<tag>", say. It
                      > does not actually move the cursor, though, which is how I would
                      > understand your "skip". The script would add "</tag>" at the cursor
                      > position.
                      I mean:

                      if you have

                      <foo>
                      <bar>
                      <foobar>
                      </bar>
                      | [<-cursor]

                      and press <C-Enter>, what would you have then ?? I think it woule be
                      natural to get </foo>, wouldn't it ? Obviously, if you'd get
                      </foobar> if would be broken construction, and most probably not that
                      you would like to have..



                      --
                      Fortune's current rates:

                      Answers .10
                      Long answers .25
                      Answers requiring thought .50
                      Correct answers $1.00

                      Dumb looks are still free.
                    • Thomas S. Urban
                      ... [another nice script cut] Here is an improved (well, maybe just expanded) version that will automatically indent your preprocessor directives if they are
                      Message 10 of 10 , Sep 1, 2001
                        On Wed, Aug 01, 2001 at 08:29:22PM +0100, Mark Zealey wrote:
                        > On Wed, Aug 01, 2001 at 09:48:50PM +0300, Bohdan Vlasyuk wrote:
                        >
                        > > On Wed, Aug 01, 2001 at 07:38:10PM +0100, Mark Zealey wrote:
                        > >
                        > > > And vim could automatically fill in the #else and #endif with /* __foo__ */
                        > > > after them, as is commonly the style in complexed .h files.
                        >
                        > [Nice script cut]
                        >
                        >
                        > Thanks! here's a slightly fixed version which works with #ifndef too.
                        > preprocessor macro's can't have whitepsace before the # however, I believe, so I
                        > fixed that:
                        >

                        [another nice script cut]

                        Here is an improved (well, maybe just expanded) version that will
                        automatically indent your preprocessor directives if they are nested.
                        It also handles mutliple #elif directives (adding to the comments on
                        each subsequent #el* and the #endif). It uses // for C++, /* */ for C.

                        The imaps are:
                        #i -> #if (user completes to #ifdef, #ifndef, or just #if args)
                        #d -> #define
                        #u -> #undef
                        #el -> #el (user completes to #else or #elif)
                        #en -> #endif
                        (you might want to change them to the full words if you don't like
                        suprises as you type)

                        Like the inspiring script, comment adding is only triggered for the #en
                        mapping. All the others do the nested indenting. So if I type this:

                        #idef BILL
                        #indef BOB
                        #d FRED
                        #en
                        #en
                        #i 1
                        #i !defined(BILL)
                        #elif defined(FRED)
                        #elif defined(F) || !defined(R)
                        #d 2 3
                        #else
                        #idef TRUE
                        #d 3 2
                        #en
                        #en
                        #u BOB
                        #en

                        I get this output (with ts=2):

                        #ifdef BILL
                        # ifndef BOB
                        # define FRED
                        # endif /* !BOB */
                        #endif /* BILL */
                        #if 1
                        # if !defined(BILL)
                        # elif defined(FRED) /* !defined(BILL) */
                        # elif defined(F) || !defined(R) /* !defined(BILL) + defined(FRED) */
                        # define 2 3
                        # else /* !defined(BILL) + defined(FRED) + defined(F) || !defined(R) */
                        # ifdef TRUE
                        # define 3 2
                        # endif /* TRUE */
                        # endif /* !defined(BILL) + defined(FRED) + defined(F) || !defined(R) */
                        # undef BOB
                        #endif /* 1 */

                        If you don't find this indenting style attractive, you might find this
                        all that useful. It's implemented with two functions though, so you
                        could separate them. Moderated numbers of #elif's can produce really
                        long comments.



                        Scott

                        --
                        If all men were brothers, would you let one marry your sister?
                      Your message has been successfully submitted and would be delivered to recipients shortly.