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

Re: patch for missing autoindent when 'InsertCharPre *' autocmd defined

Expand Messages
  • Alexey Radkov
    Thank you! After patch 7.3.534 it works fine. Cheers, Alexey. 2012/5/29 Alexey Radkov ... -- You received this message from the
    Message 1 of 9 , Jun 1, 2012
    View Source
    • 0 Attachment
      Thank you!

      After patch 7.3.534 it works fine.

      Cheers, Alexey.


      2012/5/29 Alexey Radkov <alexey.radkov@...>
      Here is variant with buffer allocated on stack (patch attached):


          static char_u *
      do_insert_char_pre(c)
          int c;
      {
          char_u    *res = NULL;
      #ifdef FEAT_MBYTE
          char_u    buf[MB_MAXBYTES];
      #else
          char_u    buf[2];
      #endif


          /* Return quickly when there is nothing to do. */
          if (!has_insertcharpre())
          return NULL;

      #ifdef FEAT_MBYTE
          if (has_mbyte)
          buf[(*mb_char2bytes)(c, buf)] = NUL;
          else
      #endif
          {
          buf[0] = c;
          buf[1] = NUL;

          }

          /* Lock the text to avoid weird things from happening. */
          ++textlock;
          set_vim_var_string(VV_CHAR, buf, -1);  /* set v:char */


          if (apply_autocmds(EVENT_INSERTCHARPRE, NULL, NULL, FALSE, curbuf))
          /* Get the new value of v:char.  It may be empty or more than one
           * character. */
          if (strcmp(buf, get_vim_var_str(VV_CHAR)))
              res = vim_strsave(get_vim_var_str(VV_CHAR));


          set_vim_var_string(VV_CHAR, NULL, -1);  /* clear v:char */
          --textlock;

          return res;
      }

      2012/5/29 Alexey Radkov <alexey.radkov@...>
      Btw it is expensive to allocate memory for 'char_u* old' in the latest patch. Instead it makes sense to do something like in eval.c in function set_vim_var_char() where a buffer is allocated on stack.


      2012/5/28 Alexey Radkov <alexey.radkov@...>
      I found a better solution.

      The problematic piece in edit() is

              if (!p_paste)
              {
              /* Trigger InsertCharPre. */
              char_u *str = do_insert_char_pre(c);
              char_u *p;

              if (str != NULL)
              {
                  if (*str != NUL && stop_arrow() != FAIL)
                  {
                  /* Insert the new value of v:char literally. */
                  for (p = str; *p != NUL; mb_ptr_adv(p))
                  {
                      c = PTR2CHAR(p);
                      if (c == CAR || c == K_KENTER || c == NL)
                      ins_eol(c);
                      else
                      ins_char(c);
                  }
                  AppendToRedobuffLit(str, -1);
                  }
                  vim_free(str);
                  c = NUL;
              }

              /* If the new value is already inserted or an empty string
               * then don't insert any character. */
              if (c == NUL)
                  break;
              }

      (i removed lines i inserted in previous patch). do_insert_char_pre() always returns not null so we go into block 'if (str != NULL)' and eventually break out of the wrapping for-loop skipping indentation, textwidth processing etc. Better solution is to make do_insert_char_pre() return NULL if VV_CHAR has not been changed: it will ensure that we do not break the for-loop in case of autocmds which do not change VV_CHAR like


      autocmd InsertCharPre * let a = 1

      I changed do_insert_char_pre() to make it return NULL if VV_CHAR is not changed:

          static char_u *
      do_insert_char_pre(c)
          int c;
      {
          char_u *res = NULL, *old;

          /* Return quickly when there is nothing to do. */
          if (!has_insertcharpre())
          return NULL;

          /* Lock the text to avoid weird things from happening. */
          ++textlock;
          set_vim_var_char(c);  /* set v:char */

          old = vim_strsave(get_vim_var_str(VV_CHAR));

          if (apply_autocmds(EVENT_INSERTCHARPRE, NULL, NULL, FALSE, curbuf))
          /* Get the new value of v:char.  It may be empty or more than one
           * character. */
          if (old && strcmp(old, get_vim_var_str(VV_CHAR)))
              res = vim_strsave(get_vim_var_str(VV_CHAR));

          vim_free(old);
          set_vim_var_string(VV_CHAR, NULL, -1);  /* clear v:char */
          --textlock;

          return res;
      }

      Now it works fine for autoindenting and textwidth. New patch is (also attached):


      diff -r 1c6b099ead89 src/edit.c
      --- a/src/edit.c    Sun May 27 00:37:51 2012 +0200
      +++ b/src/edit.c    Mon May 28 23:36:12 2012 +0400
      @@ -10108,7 +10108,7 @@
       do_insert_char_pre(c)
           int c;
       {
      -    char_u *res;
      +    char_u *res = NULL, *old;
       
           /* Return quickly when there is nothing to do. */
           if (!has_insertcharpre())
      @@ -10118,13 +10118,15 @@
           ++textlock;
           set_vim_var_char(c);  /* set v:char */
       
      +    old = vim_strsave(get_vim_var_str(VV_CHAR));
      +
           if (apply_autocmds(EVENT_INSERTCHARPRE, NULL, NULL, FALSE, curbuf))
           /* Get the new value of v:char.  It may be empty or more than one
            * character. */
      -    res = vim_strsave(get_vim_var_str(VV_CHAR));
      -    else
      -    res = NULL;
      -
      +    if (old && strcmp(old, get_vim_var_str(VV_CHAR)))
      +        res = vim_strsave(get_vim_var_str(VV_CHAR));
      +
      +    vim_free(old);
           set_vim_var_string(VV_CHAR, NULL, -1);  /* clear v:char */
           --textlock;


      Cheers, Alexey.




      2012/5/28 Alexey Radkov <alexey.radkov@...>
      Just found that automatic line break when textwidth is set is also broken.


      2012/5/28 Bram Moolenaar <Bram@...>

      Alexey Radkov wrote:

      > It is simple.
      >
      > Open some C/C++ code in vim (after patch 461), then
      >
      > :set cinoptions=:0(0+2s    "this does not really matter, just my settings
      > :set cindent
      > :autocmd InsertCharPre * let a = 1
      >
      > write something like
      >
      > int a()
      >     {
      >
      > Now after you insert <CR> '{' must move to the left as you use cindent.
      > After patch 461 it will stay.
      > Further, if you use cvim, a closing brace after <CR> will be inserted.
      > After patch 461 this will look this way:
      >
      > int a()
      >     {
      >         <CURSOR>
      >         }
      >
      > <<<  MUST BE
      >
      > int a()
      > {
      >     <CURSOR>
      > }
      >
      > >>>
      >
      > The problem is that in case if InsertCharPre is defined for '*' it will
      > always trigger and prevent autoindent of cindent! I am not sure that the
      > patch that i sent is completely correct: it just fixes the problem for me.
      >
      > Cheers, Alexey.

      Yasuhiro, can you reproduce this?

      --
      login: yes
      password: I don't know, please tell me
      password is incorrect
      login: yes
      password: incorrect

       /// Bram Moolenaar -- Bram@... -- http://www.Moolenaar.net   \\\
      ///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
      \\\  an exciting new programming language -- http://www.Zimbu.org        ///
       \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///





      --
      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
    Your message has been successfully submitted and would be delivered to recipients shortly.