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

BUG: g ignores range in diff mode

Expand Messages
  • Gary Johnson
    When vim is in diff mode and a BufWrite autocommand containing a g is executed, the g command appears to ignore the range and act on the entire
    Message 1 of 6 , Aug 4, 2008
    • 0 Attachment
      When vim is in diff mode and a BufWrite autocommand containing a
      "<range>g" is executed, the g command appears to ignore the range
      and act on the entire buffer.

      Here's an example.

      Create a file containing the integers from 1 to 1000, each on a
      separate line:

      $ seq 1000 > seq1

      Create the following vim script and name it "test1.vim":

      au BufWrite * 1,100g/50$/s/$/\tchanged here/

      When that autocommand is triggered by writing the buffer, it should
      append "\tchanged here" to every line in the range 1 to 100 ending
      in "50". That is, it should change line 50 and only line 50.

      Now edit seq1 with vim, source the script, open a new buffer, and
      read seq1 into that buffer:

      $ vim -N -u NONE -i NONE -c 'so test1.vim' -c 'vnew|r seq1|normal ggdd' seq1

      There's nothing magic about doing that on the command line--I just
      got tired of typing all those vim commands as I worked on making the
      example smaller.

      Now move the cursor to the right window (^W^W) and write the buffer
      to the seq1 file by executing:

      :w

      Note that line 50 and only line 50 has changed to:

      50 changed here

      This is as it should be.

      Now diff the two buffers:

      :windo diffthis

      and write the right buffer again:

      :w

      Note now that every line in the file ending in "50" (i.e., 150, 250,
      350, 450, 550, 650, 750, 850 and 950) has been appended with
      "changed here". This appears to be a bug.


      I am using vim-7.2b (no patches) on a machine running Red Hat
      Enterprise Linux WS release 4 (Nahant Update 5). The output of "vim
      --version" is:

      VIM - Vi IMproved 7.2b BETA (2008 Jul 13, compiled Jul 15 2008 13:42:47)
      Compiled by garyjohn@...
      Normal version with GTK2 GUI. Features included (+) or not (-):
      -arabic +autocmd +balloon_eval +browse +builtin_terms +byte_offset +cindent
      +clientserver +clipboard +cmdline_compl +cmdline_hist +cmdline_info +comments
      +cryptv +cscope +cursorshape +dialog_con_gui +diff +digraphs +dnd -ebcdic
      -emacs_tags +eval +ex_extra +extra_search -farsi +file_in_path +find_in_path
      +float +folding -footer +fork() +gettext -hangul_input +iconv +insert_expand
      +jumplist -keymap -langmap +libcall +linebreak +lispindent +listcmds +localmap
      +menu +mksession +modify_fname +mouse +mouseshape -mouse_dec +mouse_gpm
      -mouse_jsbterm -mouse_netterm -mouse_sysmouse +mouse_xterm +multi_byte
      +multi_lang -mzscheme +netbeans_intg -osfiletype +path_extra -perl +postscript
      +printer -profile -python +quickfix +reltime -rightleft -ruby +scrollbind
      +signs +smartindent -sniff +statusline -sun_workshop +syntax +tag_binary
      +tag_old_static -tag_any_white -tcl +terminfo +termresponse +textobjects +title
      +toolbar +user_commands +vertsplit +virtualedit +visual +visualextra +viminfo
      +vreplace +wildignore +wildmenu +windows +writebackup +X11 -xfontset +xim
      +xsmp_interact +xterm_clipboard -xterm_save
      system vimrc file: "$VIM/vimrc"
      user vimrc file: "$HOME/.vimrc"
      user exrc file: "$HOME/.exrc"
      system gvimrc file: "$VIM/gvimrc"
      user gvimrc file: "$HOME/.gvimrc"
      system menu file: "$VIMRUNTIME/menu.vim"
      fall-back for $VIM: "/home/garyjohn/src/Linux/vim-7.2b/share/vim"
      Compilation: gcc -c -I. -Iproto -DHAVE_CONFIG_H -DFEAT_GUI_GTK -DXTHREADS -D_REENTRANT -DXUSE_MTSAFE_API -I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/X11R6/include -I/usr/include/atk-1.0 -I/usr/include/pango-1.0 -I/usr/include/freetype2 -I/usr/include/freetype2/config -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -g -O2 -I/usr/X11R6/include
      Linking: gcc -L/usr/X11R6/lib -L/usr/local/lib -o vim -Wl,--export-dynamic -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lpangoxft-1.0 -lpangox-1.0 -lpango-1.0 -lgobject-2.0 -lgmodule-2.0 -lglib-2.0 -lXt -lm -lncurses -lselinux -lacl -lgpm


      Regards,
      Gary


      --~--~---------~--~----~------------~-------~--~----~
      You received this message from the "vim_dev" maillist.
      For more information, visit http://www.vim.org/maillist.php
      -~----------~----~----~----~------~----~------~--~---
    • John Beckett
      ... I ve had a look at this and confirm Gary s results. It looks like a bug. I don t follow all the complex interactions, but the following looks as if it is
      Message 2 of 6 , Aug 5, 2008
      • 0 Attachment
        Gary Johnson wrote:
        > When vim is in diff mode and a BufWrite autocommand
        > containing a "<range>g" is executed, the g command appears to
        > ignore the range and act on the entire buffer.
        > ...

        I've had a look at this and confirm Gary's results. It looks like a bug.

        I don't follow all the complex interactions, but the following looks as if it is
        responsible.

        In file ex_docmd.c the function do_one_cmd() is invoked by the autocmd.
        Everything is good at entry. The command is:
        "1,100g/50$/s/$/\tchanged here/"

        and it is parsed correctly including:
        ea.line1 = 1
        ea.line2 = 100

        But then the following code is executed:
        if (((ea.argt & WHOLEFOLD) || ea.addr_count >= 2) && !global_busy)
        {
        /* Put the first line at the start of a closed fold, put the last line
        * at the end of a closed fold. */
        (void)hasFolding(ea.line1, &ea.line1, NULL);
        (void)hasFolding(ea.line2, NULL, &ea.line2);
        }

        The last line changes ea.line2 from 100 to 1000 (we previously did ':windo diffthis'
        which folded a lot of lines, ending at line 1000).

        Therefore the 'g' command is applied to the whole file and Gary's bug follows.

        John



        --~--~---------~--~----~------------~-------~--~----~
        You received this message from the "vim_dev" maillist.
        For more information, visit http://www.vim.org/maillist.php
        -~----------~----~----~----~------~----~------~--~---
      • Bram Moolenaar
        ... Not a bug. When folds are closed the operation applies to the whole fold. See :he E493 and scroll up a bit. Or :he fold-behavior . -- Why isn t there
        Message 3 of 6 , Aug 5, 2008
        • 0 Attachment
          Gary Johnson wrote:

          > When vim is in diff mode and a BufWrite autocommand containing a
          > "<range>g" is executed, the g command appears to ignore the range
          > and act on the entire buffer.
          >
          > Here's an example.
          >
          > Create a file containing the integers from 1 to 1000, each on a
          > separate line:
          >
          > $ seq 1000 > seq1
          >
          > Create the following vim script and name it "test1.vim":
          >
          > au BufWrite * 1,100g/50$/s/$/\tchanged here/
          >
          > When that autocommand is triggered by writing the buffer, it should
          > append "\tchanged here" to every line in the range 1 to 100 ending
          > in "50". That is, it should change line 50 and only line 50.
          >
          > Now edit seq1 with vim, source the script, open a new buffer, and
          > read seq1 into that buffer:
          >
          > $ vim -N -u NONE -i NONE -c 'so test1.vim' -c 'vnew|r seq1|normal ggdd' seq1
          >
          > There's nothing magic about doing that on the command line--I just
          > got tired of typing all those vim commands as I worked on making the
          > example smaller.
          >
          > Now move the cursor to the right window (^W^W) and write the buffer
          > to the seq1 file by executing:
          >
          > :w
          >
          > Note that line 50 and only line 50 has changed to:
          >
          > 50 changed here
          >
          > This is as it should be.
          >
          > Now diff the two buffers:
          >
          > :windo diffthis
          >
          > and write the right buffer again:
          >
          > :w
          >
          > Note now that every line in the file ending in "50" (i.e., 150, 250,
          > 350, 450, 550, 650, 750, 850 and 950) has been appended with
          > "changed here". This appears to be a bug.

          Not a bug. When folds are closed the operation applies to the whole
          fold. See ":he E493" and scroll up a bit. Or ":he fold-behavior".

          --
          Why isn't there mouse-flavored cat food?

          /// Bram Moolenaar -- Bram@... -- http://www.Moolenaar.net \\\
          /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
          \\\ download, build and distribute -- http://www.A-A-P.org ///
          \\\ help me help AIDS victims -- http://ICCF-Holland.org ///

          --~--~---------~--~----~------------~-------~--~----~
          You received this message from the "vim_dev" maillist.
          For more information, visit http://www.vim.org/maillist.php
          -~----------~----~----~----~------~----~------~--~---
        • Gary Johnson
          ... Oh. I can see now that the behavior is intended, but it is certainly unexpected. I don t see the benefit of having an explicit range ignored just because
          Message 4 of 6 , Aug 5, 2008
          • 0 Attachment
            On 2008-08-05, Bram Moolenaar <Bram@...> wrote:
            > Gary Johnson wrote:
            >
            > > When vim is in diff mode and a BufWrite autocommand containing a
            > > "<range>g" is executed, the g command appears to ignore the range
            > > and act on the entire buffer.
            > >
            > > Here's an example.
            > >
            > > Create a file containing the integers from 1 to 1000, each on a
            > > separate line:
            > >
            > > $ seq 1000 > seq1
            > >
            > > Create the following vim script and name it "test1.vim":
            > >
            > > au BufWrite * 1,100g/50$/s/$/\tchanged here/
            > >
            > > When that autocommand is triggered by writing the buffer, it should
            > > append "\tchanged here" to every line in the range 1 to 100 ending
            > > in "50". That is, it should change line 50 and only line 50.
            > >
            > > Now edit seq1 with vim, source the script, open a new buffer, and
            > > read seq1 into that buffer:
            > >
            > > $ vim -N -u NONE -i NONE -c 'so test1.vim' -c 'vnew|r seq1|normal ggdd' seq1
            > >
            > > There's nothing magic about doing that on the command line--I just
            > > got tired of typing all those vim commands as I worked on making the
            > > example smaller.
            > >
            > > Now move the cursor to the right window (^W^W) and write the buffer
            > > to the seq1 file by executing:
            > >
            > > :w
            > >
            > > Note that line 50 and only line 50 has changed to:
            > >
            > > 50 changed here
            > >
            > > This is as it should be.
            > >
            > > Now diff the two buffers:
            > >
            > > :windo diffthis
            > >
            > > and write the right buffer again:
            > >
            > > :w
            > >
            > > Note now that every line in the file ending in "50" (i.e., 150, 250,
            > > 350, 450, 550, 650, 750, 850 and 950) has been appended with
            > > "changed here". This appears to be a bug.
            >
            > Not a bug. When folds are closed the operation applies to the whole
            > fold. See ":he E493" and scroll up a bit. Or ":he fold-behavior".

            Oh. I can see now that the behavior is intended, but it is
            certainly unexpected. I don't see the benefit of having an explicit
            range ignored just because the range happens to be in a closed fold.

            The actual problem is that I wish to update a file's header comment
            with the modification date and time whenever the buffer is written.
            To this end, I have a function that's called by a BufWrite
            autocommand and which updates a line matching '^ \?\* *Modified:'
            in the file header. Most of the files I work on have only one such
            line, but some of the files I've been working on recently have the
            same string in each function header, so it's important to restrict
            the range to just the file header.

            Before checking a file into our revision control system, I diff the
            checked-out version with the previous version to make sure I haven't
            left any debug droppings. I usually write the file while the diff
            and folds are still enabled. The top of the file may not even
            on-screen at the time.

            So, is there any way to restrict a range within a closed fold?
            :folddopen and :folddoclosed don't seem to cut it since the range
            I'm interested in may span one or more fold boundaries. If there
            isn't a way, I suppose I could search for the bottom of the file
            header, note the line number, search for the first "Modified" line,
            note that line number, and compare line numbers before making the
            change. If I do that, it looks like I'll have to use getline() and
            setline() rather than :s for the reasons given in ":help
            fold-behavior".

            Regards,
            Gary


            --~--~---------~--~----~------------~-------~--~----~
            You received this message from the "vim_dev" maillist.
            For more information, visit http://www.vim.org/maillist.php
            -~----------~----~----~----~------~----~------~--~---
          • Tony Mechelynck
            ... You may want to open all folds before applying your range-command. And possibly to fold them afterwards, or (if possible) to save and restore the fold
            Message 5 of 6 , Aug 5, 2008
            • 0 Attachment
              On 05/08/08 23:51, Gary Johnson wrote:
              > On 2008-08-05, Bram Moolenaar<Bram@...> wrote:
              >> Gary Johnson wrote:
              >>
              >>> When vim is in diff mode and a BufWrite autocommand containing a
              >>> "<range>g" is executed, the g command appears to ignore the range
              >>> and act on the entire buffer.
              >>>
              >>> Here's an example.
              >>>
              >>> Create a file containing the integers from 1 to 1000, each on a
              >>> separate line:
              >>>
              >>> $ seq 1000> seq1
              >>>
              >>> Create the following vim script and name it "test1.vim":
              >>>
              >>> au BufWrite * 1,100g/50$/s/$/\tchanged here/
              >>>
              >>> When that autocommand is triggered by writing the buffer, it should
              >>> append "\tchanged here" to every line in the range 1 to 100 ending
              >>> in "50". That is, it should change line 50 and only line 50.
              >>>
              >>> Now edit seq1 with vim, source the script, open a new buffer, and
              >>> read seq1 into that buffer:
              >>>
              >>> $ vim -N -u NONE -i NONE -c 'so test1.vim' -c 'vnew|r seq1|normal ggdd' seq1
              >>>
              >>> There's nothing magic about doing that on the command line--I just
              >>> got tired of typing all those vim commands as I worked on making the
              >>> example smaller.
              >>>
              >>> Now move the cursor to the right window (^W^W) and write the buffer
              >>> to the seq1 file by executing:
              >>>
              >>> :w
              >>>
              >>> Note that line 50 and only line 50 has changed to:
              >>>
              >>> 50 changed here
              >>>
              >>> This is as it should be.
              >>>
              >>> Now diff the two buffers:
              >>>
              >>> :windo diffthis
              >>>
              >>> and write the right buffer again:
              >>>
              >>> :w
              >>>
              >>> Note now that every line in the file ending in "50" (i.e., 150, 250,
              >>> 350, 450, 550, 650, 750, 850 and 950) has been appended with
              >>> "changed here". This appears to be a bug.
              >> Not a bug. When folds are closed the operation applies to the whole
              >> fold. See ":he E493" and scroll up a bit. Or ":he fold-behavior".
              >
              > Oh. I can see now that the behavior is intended, but it is
              > certainly unexpected. I don't see the benefit of having an explicit
              > range ignored just because the range happens to be in a closed fold.
              >
              > The actual problem is that I wish to update a file's header comment
              > with the modification date and time whenever the buffer is written.
              > To this end, I have a function that's called by a BufWrite
              > autocommand and which updates a line matching '^ \?\* *Modified:'
              > in the file header. Most of the files I work on have only one such
              > line, but some of the files I've been working on recently have the
              > same string in each function header, so it's important to restrict
              > the range to just the file header.
              >
              > Before checking a file into our revision control system, I diff the
              > checked-out version with the previous version to make sure I haven't
              > left any debug droppings. I usually write the file while the diff
              > and folds are still enabled. The top of the file may not even
              > on-screen at the time.
              >
              > So, is there any way to restrict a range within a closed fold?
              > :folddopen and :folddoclosed don't seem to cut it since the range
              > I'm interested in may span one or more fold boundaries. If there
              > isn't a way, I suppose I could search for the bottom of the file
              > header, note the line number, search for the first "Modified" line,
              > note that line number, and compare line numbers before making the
              > change. If I do that, it looks like I'll have to use getline() and
              > setline() rather than :s for the reasons given in ":help
              > fold-behavior".
              >
              > Regards,
              > Gary

              You may want to open all folds before applying your range-command. And
              possibly to fold them afterwards, or (if possible) to save and restore
              the fold level.


              Best regards,
              Tony.
              --
              hundred-and-one symptoms of being an internet addict:
              98. The Alta Vista administrators ask you what sites are missing
              in their index files.

              --~--~---------~--~----~------------~-------~--~----~
              You received this message from the "vim_dev" maillist.
              For more information, visit http://www.vim.org/maillist.php
              -~----------~----~----~----~------~----~------~--~---
            • Ben Schmidt
              ... Just set nofoldenable and then set foldenable when you re done. It s the standard way to temporarily disable folds. Ben.
              Message 6 of 6 , Aug 5, 2008
              • 0 Attachment
                > The actual problem is that I wish to update a file's header comment
                > with the modification date and time whenever the buffer is written.
                > To this end, I have a function that's called by a BufWrite
                > autocommand and which updates a line matching '^ \?\* *Modified:'
                > in the file header. Most of the files I work on have only one such
                > line, but some of the files I've been working on recently have the
                > same string in each function header, so it's important to restrict
                > the range to just the file header.
                >
                > Before checking a file into our revision control system, I diff the
                > checked-out version with the previous version to make sure I haven't
                > left any debug droppings. I usually write the file while the diff
                > and folds are still enabled. The top of the file may not even
                > on-screen at the time.
                >
                > So, is there any way to restrict a range within a closed fold?

                Just set nofoldenable and then set foldenable when you're done. It's the
                standard way to temporarily disable folds.

                Ben.




                --~--~---------~--~----~------------~-------~--~----~
                You received this message from the "vim_dev" maillist.
                For more information, visit http://www.vim.org/maillist.php
                -~----------~----~----~----~------~----~------~--~---
              Your message has been successfully submitted and would be delivered to recipients shortly.