[vim/vim] Reading from stdin via `vim -` causes vim to mark the buffer as modified (#5571)

25 views
Skip to first unread message

Ian Howell

unread,
Feb 3, 2020, 2:51:42 PM2/3/20
to vim/vim, Subscribed

Describe the bug
Reading from stdin (i.e. vim -) causes vim to mark the buffer as modified. This prevents a user from quitting with :q, and instead must resort to :q!. This behavior runs contrary to what is documented under :h --, which states that "The buffer will not be marked as modified, so that it's easy to exit".

This also prevents vim from opening to stdin in readonly mode, i.e. ls | vim -R - causes vim to exit with the error W10: Warning: Changing a readonly file, followed by Vim: Error reading input, exiting.... This entirely prevents the view command from reading from stdin.

To Reproduce
Run any command that produces output on stdout and pipe to vim -.
Examples:

echo "hello" | vim -     # Opens with the string "hello", but must be closed with :q!
echo "hello" | vim -R -  # Fails to open vim
echo "hello" | view      # Fails to open vim

The behavior can also be reproduced by running vim - alone, typing in some text, then sending the EOF signal, for example:

vim -             # Enter
this is a test    # Enter
# ctrl-d

The bug does not occur when using the previous example with vim -R -, in which case the buffer is not marked as modified, and behavior is as expected.

Expected behavior
Vim should open with the contents of stdin. The buffer should not be marked as modified.

Environment:

  • Vim version: 8.2.110
  • OS: Ubuntu 18.04,
  • Terminal: GNOME Terminal


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or unsubscribe.

Gary Johnson

unread,
Feb 3, 2020, 4:02:08 PM2/3/20
to reply+ACY5DGELPYGO7CE7RM...@reply.github.com, vim...@googlegroups.com
On 2020-02-03, Ian Howell wrote:
> Describe the bug
> Reading from stdin (i.e. vim -) causes vim to mark the buffer as modified. This
> prevents a user from quitting with :q, and instead must resort to :q!. This
> behavior runs contrary to what is documented under :h --, which states that
> "The buffer will not be marked as modified, so that it's easy to exit".

Interesting. It has worked that way for as long as I can remember;
I thought it was supposed to work that way. In fact, I have the
following in my vimrc to work around the issue.

autocmd StdinReadPost * set nomodified

> This also prevents vim from opening to stdin in readonly mode, i.e. ls | vim -R
> - causes vim to exit with the error W10: Warning: Changing a readonly file,
> followed by Vim: Error reading input, exiting.... This entirely prevents the
> view command from reading from stdin.
>
> To Reproduce
> Run any command that produces output on stdout and pipe to vim -.
> Examples:
>
> echo "hello" | vim - # Opens with the string "hello", but must be closed with :q!
> echo "hello" | vim -R - # Fails to open vim
> echo "hello" | view # Fails to open vim
>
> The behavior can also be reproduced by running vim - alone, typing in some
> text, then sending the EOF signal, for example:
>
> vim - # Enter
> this is a test # Enter
> # ctrl-d
>
> The bug does not occur when using the previous example with vim -R -, in which
> case the buffer is not marked as modified, and behavior is as expected.

I can reproduce your results with "vim -", but not with "vim -R -"
or "view -". The latter open vim and allow :q to quit. I actually
tested with "-N -u NONE" added to your commands to avoid the effects
of my environment:

echo "hello" | vim -N -u NONE -
echo "hello" | vim -R -N -u NONE -
echo "hello" | view -N -u NONE -

All three opened with the string "hello", but the first required :q!
to close while the last two required only :q.

However, the way I read the documentation, the current behavior of
"vim -R -" and "view -" that I observed is also wrong. The :help
says:

The buffer will not be marked as modified, so that it's easy
to exit. Be careful to mark it as modified if you don't want
to accidentally lose it. Example: >
ls | view -

That second sentence, immediately followed by the view example,
suggests that the buffer in the view example will be marked as
modified, which it currently is not.

It looks to me like there's a test in the Vim code that's handled
backwards. From a cursory look at the code, it looks like it might
be this, in the read_buffer() function in buffer.c.

if (read_stdin)
{
// Set or reset 'modified' before executing autocommands, so that
// it can be changed there.
if (!readonlymode && !BUFEMPTY())
changed();
else if (retval == OK)
unchanged(curbuf, FALSE, TRUE);

or perhaps this, executed later in open_buffer(), also in buffer.c.
Those first two sentences appear to contradict the :help.

// When reading stdin, the buffer contents always needs writing, so set
// the changed flag. Unless in readonly mode: "ls | gview -".
// When interrupted and 'cpoptions' contains 'i' set changed flag.
if ((got_int && vim_strchr(p_cpo, CPO_INTMOD) != NULL)
|| modified_was_set // ":set modified" used in autocmd
#ifdef FEAT_EVAL
|| (aborting() && vim_strchr(p_cpo, CPO_INTMOD) != NULL)
#endif
)
changed();
else if (retval == OK && !read_stdin && !read_fifo)
unchanged(curbuf, FALSE, TRUE);

I'll take a closer look at those when I have more time.

> Expected behavior
> Vim should open with the contents of stdin. The buffer should not be marked as
> modified.
>
> Environment:
>
> • Vim version: 8.2.110
> • OS: Ubuntu 18.04,
> • Terminal: GNOME Terminal

I'm running Vim 8.2.140 on Ubuntu 18.04 in an xterm.

Regards,
Gary

vim-dev ML

unread,
Feb 3, 2020, 4:02:38 PM2/3/20
to vim/vim, vim-dev ML, Your activity
On 2020-02-03, Ian Howell wrote:
> Describe the bug
> Reading from stdin (i.e. vim -) causes vim to mark the buffer as modified. This
> prevents a user from quitting with :q, and instead must resort to :q!. This
> behavior runs contrary to what is documented under :h --, which states that
> "The buffer will not be marked as modified, so that it's easy to exit".

Interesting. It has worked that way for as long as I can remember;
I thought it was supposed to work that way. In fact, I have the
following in my vimrc to work around the issue.

autocmd StdinReadPost * set nomodified

> This also prevents vim from opening to stdin in readonly mode, i.e. ls | vim -R
> - causes vim to exit with the error W10: Warning: Changing a readonly file,
> followed by Vim: Error reading input, exiting.... This entirely prevents the
> view command from reading from stdin.
>
> To Reproduce
> Run any command that produces output on stdout and pipe to vim -.
> Examples:
>
> echo "hello" | vim - # Opens with the string "hello", but must be closed with :q!
> echo "hello" | vim -R - # Fails to open vim
> echo "hello" | view # Fails to open vim
>
> The behavior can also be reproduced by running vim - alone, typing in some
> text, then sending the EOF signal, for example:
>
> vim - # Enter
> this is a test # Enter
> # ctrl-d
>
> The bug does not occur when using the previous example with vim -R -, in which
> case the buffer is not marked as modified, and behavior is as expected.

I can reproduce your results with "vim -", but not with "vim -R -"
or "view -". The latter open vim and allow :q to quit. I actually
tested with "-N -u NONE" added to your commands to avoid the effects
of my environment:

echo "hello" | vim -N -u NONE -
echo "hello" | vim -R -N -u NONE -
echo "hello" | view -N -u NONE -

All three opened with the string "hello", but the first required :q!
to close while the last two required only :q.

However, the way I read the documentation, the current behavior of
"vim -R -" and "view -" that I observed is also wrong. The :help
says:

The buffer will not be marked as modified, so that it's easy
> Expected behavior
> Vim should open with the contents of stdin. The buffer should not be marked as
> modified.
>
> Environment:
>
> • Vim version: 8.2.110
> • OS: Ubuntu 18.04,
> • Terminal: GNOME Terminal

I'm running Vim 8.2.140 on Ubuntu 18.04 in an xterm.

Regards,
Gary

Ian Howell

unread,
Feb 3, 2020, 4:12:54 PM2/3/20
to vim/vim, vim-dev ML, Comment

Thanks for the response Gary. Embarrassingly, I believe I may have been missing the ending dash when opening vim in readonly mode in my personal tests.

Nonetheless, the behavior still contradicts the documentation


You are receiving this because you commented.

Tony Mechelynck

unread,
Feb 4, 2020, 8:30:45 AM2/4/20
to vim/vim, vim-dev ML, Comment

To avoid marking the file as modified when r'eading from stdin, use view rather than vim as the pager command.


You are receiving this because you commented.

Gary Johnson

unread,
Feb 4, 2020, 2:03:22 PM2/4/20
to reply+ACY5DGBKIF5F4L2FK4...@reply.github.com, vim...@googlegroups.com
On 2020-02-04, Tony Mechelynck wrote:
> To avoid marking the file as modified when r'eading from stdin, use view rather
> than vim as the pager command.

That's true, but is not what the documentation says.

I did some investigating with git blame. The earliest version of
the code that I could find was the apparent creation of buffer.c on
13 June 2004 for version 7.0001, commit
071d4279d6ab81b7187b48f3a0fc61e587b6db6c. It contains the comment

/* When reading stdin, the buffer contents always needs writing, so set
* the changed flag. Unless in readonly mode: "ls | gview -".

which is the same today and matches the actual behavior.

Until 18 November 2018, the documentation agreed. Until that time,
it read:

The buffer will be marked modified, because it contains text
that needs to be saved. Except when in readonly mode, then
the buffer is not marked modified. Example: >
ls | view -

On that date, with commit a2a80162deb1e96e16b097dfe48b61b6eb0824bf,
it was changed to the current, incorrect, text:

The buffer will not be marked as modified, so that it's easy
to exit. Be careful to mark it as modified if you don't want
to accidentally lose it. Example: >
ls | view -

I don't know why it was changed. Perhaps someone intended to change
the behavior but changed only the documentation, or they
misunderstood the behavior and tried to correct the documentation.
In any case, that change to the documentation should be reverted.

Regards,
Gary

vim-dev ML

unread,
Feb 4, 2020, 2:03:27 PM2/4/20
to vim/vim, vim-dev ML, Your activity
On 2020-02-04, Tony Mechelynck wrote:
> To avoid marking the file as modified when r'eading from stdin, use view rather
> than vim as the pager command.

That's true, but is not what the documentation says.

I did some investigating with git blame. The earliest version of
the code that I could find was the apparent creation of buffer.c on
13 June 2004 for version 7.0001, commit
071d4279d6ab81b7187b48f3a0fc61e587b6db6c. It contains the comment

/* When reading stdin, the buffer contents always needs writing, so set
* the changed flag. Unless in readonly mode: "ls | gview -".

which is the same today and matches the actual behavior.

Until 18 November 2018, the documentation agreed. Until that time,
it read:

The buffer will be marked modified, because it contains text
that needs to be saved. Except when in readonly mode, then
the buffer is not marked modified. Example: >
ls | view -

On that date, with commit a2a80162deb1e96e16b097dfe48b61b6eb0824bf,
it was changed to the current, incorrect, text:

The buffer will not be marked as modified, so that it's easy
to exit. Be careful to mark it as modified if you don't want
to accidentally lose it. Example: >
ls | view -

I don't know why it was changed. Perhaps someone intended to change
the behavior but changed only the documentation, or they
misunderstood the behavior and tried to correct the documentation.
In any case, that change to the documentation should be reverted.

Regards,
Gary

Bram Moolenaar

unread,
Feb 4, 2020, 5:08:55 PM2/4/20
to vim...@googlegroups.com, Gary Johnson, reply+ACY5DGBKIF5F4L2FK4...@reply.github.com
I recall we went back and forth on this. Marking the buffer as modified
is the safest, thus that's what we ended up with. If you don't like it
you can use:

" Don't set 'modified' when reading from stdin
au StdinReadPost * set nomodified

I'll update the help.

--
The only backup you need is the one that you didn't have time for.
(Murphy)

/// Bram Moolenaar -- Br...@Moolenaar.net -- 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 ///

vim-dev ML

unread,
Feb 4, 2020, 5:09:03 PM2/4/20
to vim/vim, vim-dev ML, Your activity

Gary Johnson wrote:

> On 2020-02-04, Tony Mechelynck wrote:
> > To avoid marking the file as modified when r'eading from stdin, use view rather
> > than vim as the pager command.
>
> That's true, but is not what the documentation says.
>
> I did some investigating with git blame. The earliest version of
> the code that I could find was the apparent creation of buffer.c on
> 13 June 2004 for version 7.0001, commit
> 071d4279d6ab81b7187b48f3a0fc61e587b6db6c. It contains the comment
>
> /* When reading stdin, the buffer contents always needs writing, so set
> * the changed flag. Unless in readonly mode: "ls | gview -".
>
> which is the same today and matches the actual behavior.
>
> Until 18 November 2018, the documentation agreed. Until that time,
> it read:
>
> The buffer will be marked modified, because it contains text
> that needs to be saved. Except when in readonly mode, then
> the buffer is not marked modified. Example: >
> ls | view -
>
> On that date, with commit a2a80162deb1e96e16b097dfe48b61b6eb0824bf,
> it was changed to the current, incorrect, text:
>
> The buffer will not be marked as modified, so that it's easy
> to exit. Be careful to mark it as modified if you don't want
> to accidentally lose it. Example: >
> ls | view -
>
> I don't know why it was changed. Perhaps someone intended to change
> the behavior but changed only the documentation, or they
> misunderstood the behavior and tried to correct the documentation.
> In any case, that change to the documentation should be reverted.

I recall we went back and forth on this. Marking the buffer as modified
is the safest, thus that's what we ended up with. If you don't like it
you can use:

" Don't set 'modified' when reading from stdin
au StdinReadPost * set nomodified

I'll update the help.

--
The only backup you need is the one that you didn't have time for.
(Murphy)

/// Bram Moolenaar -- Br...@Moolenaar.net -- 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 ///

Gary Johnson

unread,
Feb 4, 2020, 5:37:20 PM2/4/20
to vim...@googlegroups.com
It makes sense that it does what it does. I was more concerned that
the help didn't match the behavior. (I was also intrigued by the
difference between the two and the possibility of learning to use
Fugitive's :Gblame to explore the history.)

> If you don't like it you can use:
>
> " Don't set 'modified' when reading from stdin
> au StdinReadPost * set nomodified

I do. This is just more convenient for me for the way I typically
use Vim.

> I'll update the help.

Thanks.

Regards,
Gary

lacygoill

unread,
Dec 18, 2020, 4:16:00 AM12/18/20
to vim/vim, vim-dev ML, Comment

Fixed by ebdf3c9.

:h -- was updated to include this paragraph:

https://github.com/vim/vim/blob/0353f56ddb379e7f1a68172fa4743355e04df21e/runtime/doc/starting.txt#L62-L66


You are receiving this because you commented.

Christian Brabandt

unread,
Dec 18, 2020, 4:30:04 AM12/18/20
to vim/vim, vim-dev ML, Comment

Closed #5571.


You are receiving this because you commented.

Reply all
Reply to author
Forward
0 new messages