When Vim notices a file it is editing is deleted, it gives the "File ___ is no
longer available" message, which is pretty good.
I think it would make sense for Vim also to set 'modified' when this happens so
that abandoning a buffer whose file has been lost requires a bang (!).
Would you consider this Bram?
What do others think?
Ben.
Ben.
+1
I've been trying to think of any adverse effects this would have,
and can't come up with anything but the most contrived of
examples and none of them outweigh the value of the suggestion.
The best argument I could come up with was "it might break
scripts". But that only involves scripts that quit/leave the
file in question, AFACT. A minor pain? perhaps.
On the flip side, the cost of *not* doing this is the possiblity
that important data you _thought_ was there can be irretrievably
lost because you weren't forced to explicitly discard it.
Minor pain vs. irretrievable loss? I'll take the minor pain
please if I have a choice. :)
-tim
I don't like it. I often edit a file, decide I want to delete it, do
":!rm %" and go to another file. I can easily hit return to get past
the warning, but having to add a "!" to the next command will be
annoying.
I think the solution is to make sure you don't delete a file that you
want to keep.
--
ARTHUR: ... and I am your king ....
OLD WOMAN: Ooooh! I didn't know we had a king. I thought we were an
autonomous collective ...
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
/// Bram Moolenaar -- Br...@Moolenaar.net -- 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 ///
Ben Schmidt wrote:
> When Vim notices a file it is editing is deleted, it gives the "File ___ is no
> longer available" message, which is pretty good.
>
> I think it would make sense for Vim also to set 'modified' when this happens so
> that abandoning a buffer whose file has been lost requires a bang (!).
>
> Would you consider this Bram?
>
> What do others think?
I don't like it. I often edit a file, decide I want to delete it, do
":!rm %" and go to another file. I can easily hit return to get past
the warning, but having to add a "!" to the next command will be
annoying.
I think the solution is to make sure you don't delete a file that you
want to keep.
Very nice! I think this one might warrant a tip...
This is now installed in my vimrc! Definitely warrants a tip.
Ben.
Regards, John
I think you probably want an
echohl None
in there, too.
> I'll update the tip soon.
Great work!
Ben.
> Regards, John
in there, too.
Great work!
> I'll update the tip soon.
Ben.
> Regards, John
Do we want echomsg or echoerr instead of just echo? I'm not sure what
the "proper" choice would be in this case.
Well, the differences are as follows:
- echomsg and echoerr can be "recalled" by the ":messages" command
- echoerr aborts the calling command or function the way a Vim error would.
I believe we don't want echoerr in this case. ":echomsg" might be the
right choice, but perhaps do away with setting ":echohl Error".
Best regards,
Tony.
--
The only really good place to buy lumber is at a store where the lumber
has already been cut and attached together in the form of furniture,
finished, and put inside boxes.
-- Dave Barry, "The Taming of the Screw"
I think the echohl Error is to mimic what Vim does without the customisation,
which is a good idea, IMHO. The point of my original request was not to supress or
change the message, but simply set 'modified' in addition to it.
And indeed, investigation shows that Vim does record the message for retrieval
with :messages, in a slightly different form (E211 appended, and double quotes
used, not single):
E211: File "{filename}" no longer available
Since using :echoerr causes the script/function line number to be included as an
additional message, I suggest we do not want that, but a combination of :echohl
and :echomsg. I now have this:
echohl Error
echomsg "E211: File \"" . expand('<afile>') . "\" no longer available"
echohl None
Which seems to work the same as Vim does without the autocommand (with regard to
messages).
Ben.
Well, actually it isn't an error anymore, is it? So here is my
counter-proposal (untested):
au FileChangedShell * call fcsHandler("<afile>:p")
function fcsHandler(name)
let msg = a:name
let fcs_choice = ''
if fcs_reason == "deleted"
let msg .= " no longer available"
if a:name == expand('%:p')
let msg .= " - 'modified' set"
set modified
else
let msg .= " - cannot set 'modified'"
let msg .= " on non-current buffer"
echohl Error
let fcs_choice = "ask"
endif
elseif fcs_reason == "time"
let msg .= " timestamp changed"
elseif fcs_reason == "mode"
let msg .= " permissions changed"
elseif fcs_reason == "changed"
let msg .= " contents changed"
let fcs_choice = "ask"
elseif fcs_reason == "conflict"
let msg .= " CONFLICT --"
let msg .= " is modified, but"
let msg .= " was changed outside Vim"
let fcs_choice = "ask"
echohl Error
else " unknown values (future Vim versions?)
let msg .= " FileChangedShell reason="
let msg .= fcs_reason
let fcs_choice = "ask"
endif
echomsg msg
echohl None
endfunction
Best regards,
Tony.
--
Be wary of strong drink. It can make you shoot at tax collectors and
miss
-- Lazarus Long, "Time Enough for Love"
And indeed, investigation shows that Vim does record the message for retrieval
with :messages, in a slightly different form (E211 appended, and double quotes
used, not single):
E211: File "{filename}" no longer available
Since using :echoerr causes the script/function line number to be included as an
additional message, I suggest we do not want that, but a combination of :echohl
and :echomsg. I now have this:
echohl Error
echomsg "E211: File \"" . expand('<afile>') . "\" no longer available"
echohl None
Which seems to work the same as Vim does without the autocommand (with regard to
messages).
Ben.
I still think of it as one, but can see your point.
> So here is my counter-proposal (untested):
>
> au FileChangedShell * call fcsHandler("<afile>:p")
> function fcsHandler(name)
If nothing else, it will need a function name beginning with a capital
letter. :-)
> let msg = a:name
> let fcs_choice = ''
> if fcs_reason == "deleted"
> let msg .= " no longer available"
> if a:name == expand('%:p')
> let msg .= " - 'modified' set"
> set modified
> else
> let msg .= " - cannot set 'modified'"
> let msg .= " on non-current buffer"
> echohl Error
> let fcs_choice = "ask"
> endif
Mmm. That current buffer check is a fair call, in line with the help,
which evidently most of us didn't read too thoroughly when we hacked
together our solutions...
I don't think setting the choice to 'ask' does any good though. Asking
you to reload the buffer is a bit nonsensical when the file has been
deleted! I don't suppose it would hurt, but don't see it doing any good
either!
> elseif fcs_reason == "time"
> let msg .= " timestamp changed"
> elseif fcs_reason == "mode"
> let msg .= " permissions changed"
> elseif fcs_reason == "changed"
> let msg .= " contents changed"
> let fcs_choice = "ask"
> elseif fcs_reason == "conflict"
> let msg .= " CONFLICT --"
> let msg .= " is modified, but"
> let msg .= " was changed outside Vim"
> let fcs_choice = "ask"
> echohl Error
> else " unknown values (future Vim versions?)
> let msg .= " FileChangedShell reason="
> let msg .= fcs_reason
> let fcs_choice = "ask"
> endif
> echomsg msg
> echohl None
> endfunction
And I think I now like it. I haven't tested it either, though.
Ben.
I think in line with other comments that it's not a real error any more,
and can't be caught like an exception, etc., we should not set errmsg
either.
Ben.
Won't this work, to set modified on a non-current buffer?
echomsg 'File "'.expand('<afile>:p').'" no longer available'
call setbufvar(expand('<afile>:p'), '&mod', '1')
Good catch, by the way!
I note that when I use this solution, the tab bar does not update. How
do you force the tab bar to redraw?
Nice! I didn't know of this. Vim keeps getting new functions and things
and I just can't keep up! Even the areas I thought I knew well just keep
improving and surprising me! I reckon it should work.
> Good catch, by the way!
>
> I note that when I use this solution, the tab bar does not update. How
> do you force the tab bar to redraw?
Not sure. I wonder if :redrawstatus! would do it. I somewhat doubt it.
Maybe just :redraw would?
I guess just now one or some of us should test it...
Here it is as I think it currently stands (plus I quoted the filename
and preceded it by 'File' as before):
au FileChangedShell * call FCSHandler("<afile>:p")
function FCSHandler(name)
let msg = 'File "'.a:name.'"'
let fcs_choice = ''
if fcs_reason == "deleted"
let msg .= " no longer available - 'modified' set"
call setbufvar(expand(a:name), '&modified', '1')
elseif fcs_reason == "time"
let msg .= " timestamp changed"
elseif fcs_reason == "mode"
let msg .= " permissions changed"
elseif fcs_reason == "changed"
let msg .= " contents changed"
let fcs_choice = "ask"
elseif fcs_reason == "conflict"
let msg .= " CONFLICT --"
let msg .= " is modified, but"
let msg .= " was changed outside Vim"
let fcs_choice = "ask"
echohl Error
else " unknown values (future Vim versions?)
let msg .= " FileChangedShell reason="
let msg .= fcs_reason
let fcs_choice = "ask"
endif
echomsg msg
echohl None
endfunction
Ben.
While we're at it...
I have the handlers for "mode" and "time" do a "let
v:fcs_choice='reload'" if the buffer is not modified. I think this
should be safe, though I guess that's just my own preference. My
version control system sets files to read-only when they are not
checked out, so if I checkout a file Vim often complains at me.
Unfortunately, doing the reload hides the message we so carefully
echomsg'd.
> echohl Error
> else " unknown values (future Vim versions?)
> let msg .= " FileChangedShell reason="
> let msg .= fcs_reason
> let fcs_choice = "ask"
> endif
> echomsg msg
> echohl None
> endfunction
>
>
> Ben.
>
While we're at it...
I have the handlers for "mode" and "time" do a "let
v:fcs_choice='reload'" if the buffer is not modified. I think this
should be safe, though I guess that's just my own preference. My
version control system sets files to read-only when they are not
checked out, so if I checkout a file Vim often complains at me.
Unfortunately, doing the reload hides the message we so carefully
echomsg'd.
So that only the conflict case is marked as an error, not the others
(which are just regular messages).
Calling :redraw! will redraw the tab line (so any tabs containing the
deleted file can be updated to show it). That's the only way I found
to do it.
Using redraw! requires that you put it _before_ the echomsg but
_after_ the setbufvar (which is perfect for the function being
developed, because it can be done just after the if...endif group, but
I'm doing my own thing that is slightly different, so it bit me
briefly).
So, unless someone sees a problem, I think we have:
redraw!
-- ynck. It's a Flemish family name from the region of Ghent. Even in
this very country, there are lots of people who never spell my name
right, even after years of acquaintance. Well, you don't choose the name
you're born with, do you?
>> Well, actually it isn't an error anymore, is it?
>
> I still think of it as one, but can see your point.
>
>> So here is my counter-proposal (untested):
>>
>> au FileChangedShell * call fcsHandler("<afile>:p")
>> function fcsHandler(name)
>
> If nothing else, it will need a function name beginning with a capital
> letter. :-)
Right. Apparently I confused Vim with some other apps, where camelCase
names usually begin with a small letter.
>
>> let msg = a:name
>> let fcs_choice = ''
>> if fcs_reason == "deleted"
>> let msg .= " no longer available"
>> if a:name == expand('%:p')
>> let msg .= " - 'modified' set"
>> set modified
------------ OOPS! ------------ setlocal modified
>> else
>> let msg .= " - cannot set 'modified'"
>> let msg .= " on non-current buffer"
>> echohl Error
>> let fcs_choice = "ask"
>> endif
>
> Mmm. That current buffer check is a fair call, in line with the help,
> which evidently most of us didn't read too thoroughly when we hacked
> together our solutions...
>
> I don't think setting the choice to 'ask' does any good though. Asking
> you to reload the buffer is a bit nonsensical when the file has been
> deleted! I don't suppose it would hurt, but don't see it doing any good
> either!
The idea is not asking the user to reload the buffer but asking the user
to do something, or at least to take notice and acknowledge the
situation. Since "reload" doesn't work here, the only remaining option
is "" (do nothing, without user intervention), which might lead to
dataloss if the user quits without saving. "ask" actually falls back to
"what Vim would have done in the absence of a FileChangedShell
autocommand" -- after displaying our message.
- Even if the message gets hidden, the user can get back at it (with
":messages") -- the problem, of course, is knowing that we've displayed
something.
- If only the timestamp or the permissions changed, why reload the data?
Wouldn't it in this case just mean useless labour for the disk drive,
with the concomitant slowdown? Or if doing nothing in the "mode" case
would mean Vim wouldn't know the file had been set to readonly "behind
our backs", then why reread the file in the "time" case? I can't imagine
any benefit there.
Best regards,
Tony.
--
In a medium in which a News Piece takes a minute and an "In-Depth"
Piece takes two minutes, the Simple will drive out the Complex.
-- Frank Mankiewicz
I do the reload so that Vim will automatically detect read-only, etc.
for the file. Is there a better way to do it? If I'm viewing an
un-checked-out file, and I check it out, I want to just be able to
edit it without Vim yelling at me that it is read-only (even though it
isn't anymore). If I am in the middle of editing a file, and check it
back in, I _want_ it to automatically switch to readonly so that I
don't make a bunch of edits, try to write, and _then_ find out about
it.
The timestamp one...I just threw in for good measure. I guess that one
isn't strictly necessary.
OK, that makes sense; though I'd like some way to make that detection
without actually reading the whole file (which we already have in memory).
>
> The timestamp one...I just threw in for good measure. I guess that one
> isn't strictly necessary.
If it isn't necessary, and involves input-output overhead, then let's
keep it out, shan't we?
Best regards,
Tony.
--
It's more than magnificent -- it's mediocre.
-- Sam Goldwyn
I don't think we should do something that makes the message hard to
notice, even if it can be found with :messages. The message should
always appear, with a Hit Enter prompt if necessary.
> - If only the timestamp or the permissions changed, why reload the data?
> Wouldn't it in this case just mean useless labour for the disk drive,
> with the concomitant slowdown? Or if doing nothing in the "mode" case
> would mean Vim wouldn't know the file had been set to readonly "behind
> our backs", then why reread the file in the "time" case? I can't imagine
> any benefit there.
I think this is closing the stable door after the horse has bolted. Vim
knows that only the permissions/mode of the file has changed because it
already read the file, compared it to your buffer, and noted no change
in content. It now just has to decide which buffer to delete. The hard
drive has already had its work out.
Ben.
Which country is that, incidentally, Tony?
>>> set modified
>
> ------------ OOPS! ------------ setlocal modified
I saw that, but I don't think it is an error. The global value for
'modified' even though it exists is not ever used, AFAIK, since when
initialising a new buffer it is set to be unmodified regardless. So, I
don't think it matters. Though as a matter of style, probably setlocal
is better.
>> Mmm. That current buffer check is a fair call, in line with the help,
>> which evidently most of us didn't read too thoroughly when we hacked
>> together our solutions...
>>
>> I don't think setting the choice to 'ask' does any good though. Asking
>> you to reload the buffer is a bit nonsensical when the file has been
>> deleted! I don't suppose it would hurt, but don't see it doing any good
>> either!
>
> The idea is not asking the user to reload the buffer but asking the user
> to do something, or at least to take notice and acknowledge the
> situation. Since "reload" doesn't work here, the only remaining option
> is "" (do nothing, without user intervention), which might lead to
> dataloss if the user quits without saving. "ask" actually falls back to
> "what Vim would have done in the absence of a FileChangedShell
> autocommand" -- after displaying our message.
Mmm. But isn't "what Vim would have done..." equal to "do nothing"?
Ben.
I think you're right!
Are you thinking of making a VimTip out of this, Benjamin? I think it'd
be good for one of us to do so!
Cheers,
Ben.
Belgium
>
>>>> set modified
>> ------------ OOPS! ------------ setlocal modified
>
> I saw that, but I don't think it is an error. The global value for
> 'modified' even though it exists is not ever used, AFAIK, since when
> initialising a new buffer it is set to be unmodified regardless. So, I
> don't think it matters. Though as a matter of style, probably setlocal
> is better.
>
>>> Mmm. That current buffer check is a fair call, in line with the help,
>>> which evidently most of us didn't read too thoroughly when we hacked
>>> together our solutions...
>>>
>>> I don't think setting the choice to 'ask' does any good though. Asking
>>> you to reload the buffer is a bit nonsensical when the file has been
>>> deleted! I don't suppose it would hurt, but don't see it doing any good
>>> either!
>> The idea is not asking the user to reload the buffer but asking the user
>> to do something, or at least to take notice and acknowledge the
>> situation. Since "reload" doesn't work here, the only remaining option
>> is "" (do nothing, without user intervention), which might lead to
>> dataloss if the user quits without saving. "ask" actually falls back to
>> "what Vim would have done in the absence of a FileChangedShell
>> autocommand" -- after displaying our message.
>
> Mmm. But isn't "what Vim would have done..." equal to "do nothing"?
>
> Ben.
No, it's "pop an alert and wait for the user's response". Of course,
after the user replies we don't do anything, but at least we're sure he
got the message. (FileChangedShell can be triggered after coming back
from running a shell command, which means we can't be sure the user is
paying attention unless we wait for explicit user action.)
This discussion has become a moot point, though, since someone mentioned
setbufvar()
Best regards,
Tony.
--
ARTHUR: Now stand aside worthy adversary.
BLACK KNIGHT: (Glancing at his shoulder) 'Tis but a scratch.
ARTHUR: A scratch? Your arm's off.
"Monty Python and the Holy Grail" PYTHON (MONTY)
PICTURES LTD
I've updated it:
http://vim.wikia.com/wiki/File_no_longer_available_-_mark_buffer_modified
Good efficient work to whoever put the tip there in the first place!
Ben.
Thanks Ben. It looks good (not tested!).
FYI we keep the "==Comments==" line in tips to indicate that we're happy for readers
to add tentative material (the reader doesn't want to actually edit the tip, but
wants to raise an issue or make a suggestion, etc). There's no need to do anything
more unless you really want to -- it will be fixed as part of the normal procedure.
John
I added the function and the au-command to my .vimrc but when the function
is executing it claims that fcs_reason does not exist unless I prepend it
with v:. It also does not seem to expand <afile>:p to the actual name of
the file.
What am I doing wrong?
Regards,
Joakim
Haha. Looks like none of us tested it properly! I tested a slightly earlier
version. I have now fixed it in the tip!
Ben.
OK, cool! I've fixed that now, too. Thanks for letting me know.
And thumbs up for all the work you do on the Wiki, John. It's fantastic. It's
growing into a great resource.
Ben.
That was much better. :-D
Thanks.
Regards,
Joakim
Thanks.
Regards,
Joakim